Repository: GeorgH93/Minepacks Branch: master Commit: 793c6e036e77 Files: 115 Total size: 494.6 KB Directory structure: gitextract_o_ph2osy/ ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug.md │ │ ├── feature.md │ │ └── help.md │ └── workflows/ │ ├── codeql.yml │ ├── maven.yml │ ├── release.yml │ ├── settings.xml │ └── sonarcloud.yml ├── .gitignore ├── Components/ │ ├── Minepacks-BadRabbit-Bukkit/ │ │ ├── pom.xml │ │ └── src/ │ │ └── at/ │ │ └── pcgamingfreaks/ │ │ └── Minepacks/ │ │ └── Bukkit/ │ │ └── MinepacksBadRabbit.java │ ├── Minepacks-Bootstrap-Paper/ │ │ ├── pom.xml │ │ ├── resources/ │ │ │ └── paper-plugin.yml │ │ └── src/ │ │ └── at/ │ │ └── pcgamingfreaks/ │ │ └── Minepacks/ │ │ └── Paper/ │ │ └── MinepacksBootstrap.java │ └── Minepacks-MagicValues/ │ ├── pom.xml │ ├── resources/ │ │ └── Minepacks.properties │ └── src/ │ └── at/ │ └── pcgamingfreaks/ │ └── Minepacks/ │ └── MagicValues.java ├── LICENSE ├── Minepacks/ │ ├── pom.xml │ ├── resources/ │ │ ├── config.yml │ │ ├── lang/ │ │ │ ├── chs.yml │ │ │ ├── cht.yml │ │ │ ├── cz.yml │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ ├── es.yml │ │ │ ├── fr.yml │ │ │ ├── hu.yml │ │ │ ├── it.yml │ │ │ ├── ja.yml │ │ │ ├── lt.yml │ │ │ ├── nl.yml │ │ │ ├── pl.yml │ │ │ ├── pt.yml │ │ │ ├── ru.yml │ │ │ ├── tr.yml │ │ │ ├── uk.yml │ │ │ ├── vi.yml │ │ │ ├── zh_cn.yml │ │ │ └── zh_tw.yml │ │ ├── plugin.yml │ │ └── update.yml │ ├── src/ │ │ └── at/ │ │ └── pcgamingfreaks/ │ │ └── Minepacks/ │ │ └── Bukkit/ │ │ ├── Backpack.java │ │ ├── CancellableRunnable.java │ │ ├── Command/ │ │ │ ├── BackupCommand.java │ │ │ ├── ClearCommand.java │ │ │ ├── CommandManager.java │ │ │ ├── DebugCommand.java │ │ │ ├── HelpCommand.java │ │ │ ├── InventoryClearCommand.java │ │ │ ├── MigrateCommand.java │ │ │ ├── OpenCommand.java │ │ │ ├── PickupCommand.java │ │ │ ├── ReloadCommand.java │ │ │ ├── RestoreCommand.java │ │ │ ├── ShortcutCommand.java │ │ │ ├── SortCommand.java │ │ │ ├── UpdateCommand.java │ │ │ └── VersionCommand.java │ │ ├── CooldownManager.java │ │ ├── Database/ │ │ │ ├── Config.java │ │ │ ├── Database.java │ │ │ ├── Files.java │ │ │ ├── Helper/ │ │ │ │ ├── InventoryCompressor.java │ │ │ │ └── OldFileUpdater.java │ │ │ ├── InventorySerializer.java │ │ │ ├── Language.java │ │ │ ├── Migration/ │ │ │ │ ├── FilesToSQLMigration.java │ │ │ │ ├── Migration.java │ │ │ │ ├── MigrationCallback.java │ │ │ │ ├── MigrationManager.java │ │ │ │ ├── MigrationResult.java │ │ │ │ ├── SQLtoFilesMigration.java │ │ │ │ ├── SQLtoSQLMigration.java │ │ │ │ └── ToSQLMigration.java │ │ │ ├── MySQL.java │ │ │ ├── SQL.java │ │ │ ├── SQLite.java │ │ │ └── UnCacheStrategies/ │ │ │ ├── Interval.java │ │ │ ├── IntervalChecked.java │ │ │ ├── OnDisconnect.java │ │ │ ├── OnDisconnectDelayed.java │ │ │ └── UnCacheStrategy.java │ │ ├── ItemsCollector.java │ │ ├── Listener/ │ │ │ ├── BackpackEventListener.java │ │ │ ├── DisableShulkerboxes.java │ │ │ ├── DropOnDeath.java │ │ │ ├── ItemFilter.java │ │ │ ├── ItemShortcut.java │ │ │ ├── MinepacksListener.java │ │ │ └── WorldBlacklistUpdater.java │ │ ├── Minepacks.java │ │ ├── Permissions.java │ │ ├── Placeholder/ │ │ │ ├── PlaceholderManager.java │ │ │ └── Replacer/ │ │ │ └── AutoPickupEnabled.java │ │ ├── Placeholders.java │ │ ├── ShrinkApproach.java │ │ └── SpecialInfoWorker/ │ │ ├── NoDatabaseWorker.java │ │ └── SpecialInfoBase.java │ └── test/ │ └── src/ │ └── at/ │ └── pcgamingfreaks/ │ └── Minepacks/ │ └── Bukkit/ │ └── PermissionsTest.java ├── Minepacks-API/ │ ├── README.md │ ├── pom.xml │ └── src/ │ └── at/ │ └── pcgamingfreaks/ │ └── Minepacks/ │ └── Bukkit/ │ └── API/ │ ├── Backpack.java │ ├── Callback.java │ ├── Events/ │ │ ├── BackpackDropOnDeathEvent.java │ │ ├── InventoryClearEvent.java │ │ └── InventoryClearedEvent.java │ ├── ItemFilter.java │ ├── MinepacksCommand.java │ ├── MinepacksCommandManager.java │ ├── MinepacksPlugin.java │ └── WorldBlacklistMode.java ├── README.md └── pom.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto *.java text diff=java encoding=utf-8 *.xml text *.yml text encoding=utf-8 *.md text *.png binary diff=exif # Ignore for export .gitattributes export-ignore .gitignore export-ignore .travis export-ignore /.github/ export-ignore /.idea/ export-ignore ================================================ FILE: .github/ISSUE_TEMPLATE/bug.md ================================================ --- labels: bug name: Report a bug about: Report a bug with Minepacks --- ### Information **Environment information** *Plugin + server version info*: ``` ``` *Online mode*: *BungeeCord*: **Server/crash log** ``` ``` **Plugin config (optional)** ``` ``` ### Details **Description** **Steps to reproduce** **Expected behavior** **Other information** (e.g. detailed explanation, related issues, suggestions how to fix, links for us to have context, screenshots, etc.) ================================================ FILE: .github/ISSUE_TEMPLATE/feature.md ================================================ --- labels: enhancement name: Request a feature about: Request a feature you want to see in Minepacks. --- ### Feature request **Feature description** **How the feature is useful** ================================================ FILE: .github/ISSUE_TEMPLATE/help.md ================================================ --- labels: question name: Request help about: Request help with Minepacks. --- ### Help request **Problem** **What I have tried** ================================================ FILE: .github/workflows/codeql.yml ================================================ name: "CodeQL" on: push: branches: [ "master" ] pull_request: branches: [ "master" ] schedule: - cron: "56 15 * * 3" jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ java ] steps: - name: Checkout uses: actions/checkout@v5 - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild uses: github/codeql-action/autobuild@v4 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" ================================================ FILE: .github/workflows/maven.yml ================================================ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven name: Build on: [push, pull_request] jobs: buildAndTest: runs-on: ubuntu-latest strategy: matrix: java-version: [ 8, 11, 17, 21, 25 ] steps: - name: Checkout uses: actions/checkout@v5 - name: Set up JDK ${{ matrix.java-version }} uses: actions/setup-java@v5 with: distribution: temurin java-version: ${{ matrix.java-version }} - name: Build and test with maven run: mvn -B -s .github/workflows/settings.xml clean package --file pom.xml ================================================ FILE: .github/workflows/release.yml ================================================ # This workflow will run every time a new release is created. # It will first build the plugin using Maven, then publish it to GitHub packages and finally attach the artifacts to the release name: Build and release on: release: types: [created] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - name: Set up JDK 21 uses: actions/setup-java@v5 with: java-version: 21 distribution: temurin server-id: github settings-path: ${{ github.workspace }} # location for the settings.xml file - name: Setup workspace run: mkdir artifacts - name: Build with Maven run: | mvn -B -s .github/workflows/settings.xml install --file pom.xml cp Minepacks/target/M*.jar artifacts/ - name: Build with Maven (Standalone) run: | mvn -B -s .github/workflows/settings.xml clean install --file pom.xml -P Standalone,ExcludeBadRabbit mv Minepacks/target/M*-Standalone.jar artifacts/ - name: Build with Maven (Release) run: | mvn -B -s .github/workflows/settings.xml clean package --file pom.xml -P Release mv Minepacks/target/M*-Release.jar artifacts/ - name: Upload the artifacts uses: skx/github-action-publish-binaries@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: args: 'artifacts/M*' ================================================ FILE: .github/workflows/settings.xml ================================================ pcgf-public PCGF Public https://repo.pcgamingfreaks.at/repository/maven-public/ central,spigot-nexus,spigot-repo,placeholderapi,sonatype-nexus-snapshots,pcgf-repo,herocraftonline-repo,sk89q-repo,CodeMC,mvdw-software github ${env.GITHUB_ACTOR} ${env.GITHUB_TOKEN} ================================================ FILE: .github/workflows/sonarcloud.yml ================================================ name: SonarCloud on: push: branches: - master - dev # pull_request: # types: [opened, synchronize, reopened] jobs: build: name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 21 uses: actions/setup-java@v5 with: java-version: 21 distribution: temurin - name: Cache SonarCloud packages uses: actions/cache@v5 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages uses: actions/cache@v5 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Build and analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=GeorgH93_Minepacks ================================================ FILE: .gitignore ================================================ # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp *.bat # ========================= # Operating System Files # ========================= # OSX # ========================= .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # Temp files *.tmp *.sh # ========================= # IDE Project Files # ========================= *.classpath *.project *.prefs target/ /bin/ *.iml /.idea/ .flattened-pom.xml ================================================ FILE: Components/Minepacks-BadRabbit-Bukkit/pom.xml ================================================ 4.0.0 Minepacks-BadRabbit-Bukkit Minepacks-Parent at.pcgamingfreaks ${revision} ../../pom.xml ${revision} jar Minepacks-BadRabbit-Bukkit BadRabbit loader for Minepacks. https://www.spigotmc.org/resources/19286/ at.pcgamingfreaks Minepacks-MagicValues ${revision} provided at.pcgamingfreaks.pcgf_pluginlib pcgf_pluginlib-common ${pcgfPluginLibVersion} provided at.pcgamingfreaks BadRabbit-Bukkit 1.11 org.bukkit bukkit ${bukkitVersion} provided ================================================ FILE: Components/Minepacks-BadRabbit-Bukkit/src/at/pcgamingfreaks/Minepacks/Bukkit/MinepacksBadRabbit.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.BadRabbit.Bukkit.BadRabbit; import at.pcgamingfreaks.Minepacks.MagicValues; import at.pcgamingfreaks.Version; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; /** * Uses BadRabbit to initiate the plugin in normal or standalone mode depending on the users' environment. */ @SuppressWarnings("unused") public class MinepacksBadRabbit extends BadRabbit { @Override protected @NotNull JavaPlugin createInstance() throws Exception { Plugin pcgfPluginLib = Bukkit.getPluginManager().getPlugin("PCGF_PluginLib"); boolean standalone = true; if(pcgfPluginLib != null) { if(new Version(pcgfPluginLib.getDescription().getVersion()).olderThan(new Version(MagicValues.MIN_PCGF_PLUGIN_LIB_VERSION))) { getLogger().info("PCGF-PluginLib to old! Switching to standalone mode!"); } else { getLogger().info("PCGF-PluginLib installed. Switching to normal mode!"); standalone = false; } } else { getLogger().info("PCGF-PluginLib not installed. Switching to standalone mode!"); } if(standalone) { Class standaloneClass = Class.forName("at.pcgamingfreaks.MinepacksStandalone.Bukkit.Minepacks"); return (JavaPlugin) standaloneClass.newInstance(); } else { Class normalClass = Class.forName("at.pcgamingfreaks.Minepacks.Bukkit.Minepacks"); return (JavaPlugin) normalClass.newInstance(); } } } ================================================ FILE: Components/Minepacks-Bootstrap-Paper/pom.xml ================================================ 4.0.0 Minepacks-Bootstrap-Paper Minepacks-Parent at.pcgamingfreaks ${revision} ../../pom.xml ${revision} jar Minepacks-Bootstrap-Paper Paper API extension for Minepacks. papermc https://repo.papermc.io/repository/maven-public/ at.pcgamingfreaks.pcgf_pluginlib pcgf_pluginlib-version ${pcgfPluginLibVersion} at.pcgamingfreaks.pcgf_pluginlib pcgf_pluginlib-version_detection ${pcgfPluginLibVersion} io.papermc.paper paper-api 1.19.4-R0.1-SNAPSHOT provided at.pcgamingfreaks Minepacks-MagicValues ${version} provided clean install src resources true org.apache.maven.plugins maven-compiler-plugin 3.8.1 17 org.apache.maven.plugins maven-shade-plugin ${mavenShade.version} package shade false false at.pcgamingfreaks.pcgf_pluginlib:pcgf_pluginlib-version_detection ================================================ FILE: Components/Minepacks-Bootstrap-Paper/resources/paper-plugin.yml ================================================ name: "Minepacks" author: "${author}" version: "${pluginVersion}" api-version: "1.19" folia-supported: true main: "at.pcgamingfreaks.MinepacksStandalone.Bukkit.Minepacks" bootstrapper: "at.pcgamingfreaks.Minepacks.Paper.MinepacksBootstrap" dependencies: - name: PCGF_PluginLib required: false bootstrap: true - name: MVdWPlaceholderAPI required: false - name: PlaceholderAPI required: false load-after: - name: PCGF_PluginLib bootstrap: true - name: MVdWPlaceholderAPI - name: PlaceholderAPI ================================================ FILE: Components/Minepacks-Bootstrap-Paper/src/at/pcgamingfreaks/Minepacks/Paper/MinepacksBootstrap.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Paper; import at.pcgamingfreaks.Minepacks.MagicValues; import at.pcgamingfreaks.PCGF_PluginLibVersionDetection; import at.pcgamingfreaks.Version; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; import io.papermc.paper.plugin.bootstrap.PluginProviderContext; import java.lang.reflect.Field; @SuppressWarnings({ "UnstableApiUsage", "unused" }) public class MinepacksBootstrap implements PluginBootstrap { private static final String MAIN_CLASS_NORMAL = "at.pcgamingfreaks.Minepacks.Bukkit.Minepacks"; private static final String MAIN_CLASS_STANDALONE = "at.pcgamingfreaks.MinepacksStandalone.Bukkit.Minepacks"; public void bootstrap(@NotNull PluginProviderContext context) { } @Override public void bootstrap(@NotNull BootstrapContext bootstrapContext) { } @Override public @NotNull JavaPlugin createPlugin(@NotNull PluginProviderContext context) { try { if(checkPcgfPluginLib(context) && patchPluginMeta(context)) { Class normalClass = Class.forName(MAIN_CLASS_NORMAL); return (JavaPlugin) normalClass.newInstance(); } else { Class standaloneClass = Class.forName(MAIN_CLASS_STANDALONE); return (JavaPlugin) standaloneClass.newInstance(); } } catch(Exception e) { throw new RuntimeException("Failed to create Minepacks plugin instance!", e); } } private boolean patchPluginMeta(final @NotNull PluginProviderContext context) { try { Class pluginMetaClass = context.getConfiguration().getClass(); Field mainField = pluginMetaClass.getDeclaredField("main"); mainField.setAccessible(true); mainField.set(context.getConfiguration(), MAIN_CLASS_NORMAL); return true; } catch(Exception e) { try { context.getLogger().error("Failed to patch main class in PluginMeta! Falling back to Standalone mode!", e); } catch(Throwable ignored) { System.out.println("[Minepacks] Failed to patch main class in PluginMeta! Falling back to Standalone mode!"); e.printStackTrace(); } } return false; } private boolean checkPcgfPluginLib(final @NotNull PluginProviderContext context) { String version = PCGF_PluginLibVersionDetection.getVersionBukkit(); if (version != null) { if (new Version(version).olderThan(new Version(MagicValues.MIN_PCGF_PLUGIN_LIB_VERSION))) { logInfo("PCGF-PluginLib to old! Switching to standalone mode!", context); } else { logInfo("PCGF-PluginLib installed. Switching to normal mode!", context); return true; } } else { logInfo("PCGF-PluginLib not installed. Switching to standalone mode!", context); } return false; } //TODO remove this stupid code once the paper API stabilizes to a point where once can expect at least the logger class ot not randomly change private void logInfo(final @NotNull String message, final @NotNull PluginProviderContext context) { try { context.getLogger().info(message); } catch(Throwable t) { System.out.println("[Minepacks] Failed to log message: " + message); } } } ================================================ FILE: Components/Minepacks-MagicValues/pom.xml ================================================ 4.0.0 Minepacks-MagicValues Minepacks-Parent at.pcgamingfreaks ${revision} ../../pom.xml ${revision} jar Minepacks-MagicValues Contains the magic values used by Minepacks. clean install resources true ================================================ FILE: Components/Minepacks-MagicValues/resources/Minepacks.properties ================================================ LanguageFileVersion=${languageFileVersion} ConfigFileVersion=${configFileVersion} PCGFPluginLibVersion=${pcgfPluginLibVersion} ================================================ FILE: Components/Minepacks-MagicValues/src/at/pcgamingfreaks/Minepacks/MagicValues.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks; import org.jetbrains.annotations.NotNull; import java.io.InputStream; import java.util.Properties; public class MagicValues { public static final int LANG_VERSION; public static final int CONFIG_VERSION; public static final String MIN_PCGF_PLUGIN_LIB_VERSION; public static final String MIN_MC_VERSION_FOR_UPDATES = "1.8"; static { String pcgfPluginLibVersion = "99999", langVersion = "0", configVersion = "0"; try(InputStream propertiesStream = MagicValues.class.getClassLoader().getResourceAsStream("Minepacks.properties")) { Properties properties = new Properties(); properties.load(propertiesStream); pcgfPluginLibVersion = properties.getProperty("PCGFPluginLibVersion"); langVersion = properties.getProperty("LanguageFileVersion"); configVersion = properties.getProperty("ConfigFileVersion"); } catch(Exception e) { e.printStackTrace(); } MIN_PCGF_PLUGIN_LIB_VERSION = pcgfPluginLibVersion; // Try to parse the version strings, fall back to a known min version LANG_VERSION = tryParse(langVersion, 20); CONFIG_VERSION = tryParse(configVersion, 33); } private static int tryParse(@NotNull String string, int fallbackValue) { try { return Integer.parseInt(string); } catch (NumberFormatException ignored) { System.out.println("Failed to parse integer '" + string + "'! Falling back to: " + fallbackValue); } return fallbackValue; } private MagicValues() { /* You should not create an instance of this utility class! */ } } ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} 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 (at your option) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: Minepacks/pom.xml ================================================ 4.0.0 Minepacks Minepacks-Parent at.pcgamingfreaks ${revision} .. ${revision} jar Minepacks Minepacks is a backpack plugin with different backpack sizes, multi language support and SQLite and MySQL storage support. https://www.spigotmc.org/resources/19286/ PCGF_PluginLib ${project.groupId}.${project.artifactId}.Bukkit.${project.artifactId} Normal Release apache-snapshot https://repository.apache.org/content/repositories/snapshots/ at.pcgamingfreaks Minepacks-API ${revision} at.pcgamingfreaks Minepacks-MagicValues ${revision} at.pcgamingfreaks PluginLib ${pcgfPluginLibVersion} org.junit.jupiter junit-jupiter 5.8.2 test clean package test test/src resources true ./ LICENSE ${project.build.directory}/generated-resources maven-surefire-plugin 3.0.0-M4 org.apache.maven.plugins maven-shade-plugin ${mavenShade.version} package shade false false at.pcgamingfreaks:Minepacks-API at.pcgamingfreaks:Minepacks-MagicValues Standalone false ${project.version}-Standalone ${project.groupId}.${project.artifactId}Standalone.Bukkit.${project.artifactId} Standalone org.apache.maven.plugins maven-shade-plugin ${mavenShade.version} package shade true Standalone false false ${project.build.directory} at.pcgamingfreaks:Minepacks-API at.pcgamingfreaks:Minepacks-MagicValues at.pcgamingfreaks:PluginLib at.pcgf.libs at.pcgamingfreaks.MinepacksStandalone.libs at.pcgamingfreaks.Minepacks at.pcgamingfreaks.MinepacksStandalone at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack at.pcgamingfreaks.Minepacks.Bukkit.API.Callback at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommandManager at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode at.pcgamingfreaks.Minepacks.Bukkit.API.ItemFilter at.pcgamingfreaks.Minepacks.Bukkit.API.Events.* at.pcgamingfreaks.Minepacks.MagicValues at.pcgamingfreaks at.pcgamingfreaks.MinepacksStandalone.libs.at.pcgamingfreaks at.pcgamingfreaks.Minepacks.** at.pcgamingfreaks:PluginLib at/pcgamingfreaks/Bungee/** at/pcgamingfreaks/PluginLib/** PCGF_PluginLib.properties update.yml org.sonatype.plugins munge-maven-plugin 1.0 munge generate-sources munge STANDALONE Release false ${project.version}-Release , PCGF_PluginLib ${project.groupId}.${project.artifactId}.Bukkit.${project.artifactId}BadRabbit Release at.pcgamingfreaks Minepacks ${project.version} Standalone at.pcgamingfreaks Minepacks-BadRabbit-Bukkit ${project.version} at.pcgamingfreaks Minepacks-Bootstrap-Paper ${project.version} org.apache.maven.plugins maven-shade-plugin ${mavenShade.version} package shade true Release false false at.pcgamingfreaks:Minepacks-API at.pcgamingfreaks:Minepacks-MagicValues at.pcgamingfreaks:Minepacks-Bootstrap-Paper at.pcgamingfreaks:BadRabbit-Bukkit at.pcgamingfreaks:Minepacks-BadRabbit-Bukkit at.pcgamingfreaks:Minepacks at.pcgamingfreaks.BadRabbit at.pcgamingfreaks.Minepacks org.codehaus.mojo license-maven-plugin 2.6.0 test,provided,system true ${project.build.directory}/generated-resources/licenses-THIRD-PARTY.xml https?://(www\.)?opensource\.org/licenses/mit-license\.php https://ci.pcgamingfreaks.at/download/mit.txt https?://(www\.)?gnu\.org/licenses/gpl-3.0.txt https://ci.pcgamingfreaks.at/download/gpl-3.0.txt add-third-party generate-resources add-third-party download-licenses ================================================ FILE: Minepacks/resources/config.yml ================================================ # Minepacks Config File # Language Settings Language: # Defines the used language, and the corresponding file used. The corresponding language file will be placed in the lang folder next to the config.yml named: .yml Language: en # Options: # Overwrite (deletes all changes from the file and extracts a new language file) # Upgrade (extracts a new language file and copy's all settings from the old language file) # Update (adds the default (english) text values for all missing values, just some basic formatting) UpdateMode: Upgrade # Title to be shown for the opened inventory for everyone except the owner of the backpack. Can contain {OwnerName} (which will be replaced with the players name). BackpackTitleOther: "&b{OwnerName}'s Backpack" # The title of the inventory for the owner of the backpack. BackpackTitle: "&bBackpack" # If disabled, both the owner and 3. party player will see the BackpackTitleOther UseDynamicTitle: true # Defines if the content of the backpack get dropped on the death of a player. # If enabled, it can be disabled for individual players with the "backpack.keepOnDeath" permission. DropOnDeath: true # If this option is enabled the backpack will not drop if the keepInventory flag for the death event is set. # This should add compatibility with plugins protecting the players inventory on death (like SaveRod). But might prevent the backpack form dropping on death with some plugins. HonorKeepInventoryOnDeath: false # Defines the max amount of columns for a backpack. # The size of the user's backpack will be defined by the permission, permissions for bigger backpacks than this value will be ignored. # Can be set to anything > 0. Backpacks with more than 6 columns will have a broken UI! Sizes bigger than 9 may not work with all permission plugins. MaxSize: 6 # Defines how backpacks get compressed when the previous permissions allowed for a bigger backpack. # Options: # Fast: Only free slots will be used # Compress: The plugin will try to combine item stacks to their max height # Sort: The plugin will sort the backpack, will leave the same amount of items that do not fit in the backpack as compress, but will leave a sorted backpack, at the cost of some extra performance ShrinkApproach: Sort # Defines in which game-modes a player can access his backpack (name or id) # Options: ADVENTURE, CREATIVE, SPECTATOR, SURVIVAL # AllowedGameModes: [ "SURVIVAL", "ADVENTURE" ] AllowedGameModes: [ "SURVIVAL" ] Cooldown: # Defines how long a player have to wait till he can reopen his backpack. # Time is in seconds. Values < 1 disable the cooldown. Command: -1 # If enabled, cooldowns will be synced between servers (BungeeCord network). It will also allow keeping the cooldown through server restarts. # You should only use it with long cooldown times. Sync: false AddOnJoin: true # You can turn this on when using sync to reduce the memory consumption a little ClearOnLeave: false # Removes old cooldowns from the cache to free memory. Time in seconds. CleanupInterval: 600 # Controls for the auto pickup on full inventory function FullInventory: # If items should be collected to the backpack if the players inventory is full. # This is also the default if 'IsToggleAllowed' is enabled. CollectItems: false # Interval in seconds how often items around the player should be collected, increase it if it lags the server CheckInterval: 1 # Radius in which items get collected, in meter/blocks, allow decimals CollectRadius: 1.5 # If this feature may be toggled. IsToggleAllowed: false # Database settings Database: # Database type. MySQL, SQLite, Files (data is stored in files, one file per user) or Shared (use shared connection pool from PCGF PluginLib) Type: SQLite # Auto database cleanup settings AutoCleanup: # Defines the max amount of days backpacks will be stored. -1 to disable auto cleanup MaxInactiveDays: -1 # Defines the storage format for UUIDs for compatibility with other plugins (shared tables) # true: format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # false: format: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx UseUUIDSeparators: false # Options: auto, online, offline | auto will decide based on the server online mode option. # If you are using BungeeCord, set it to whatever you use on your BungeeCord server!!! UUID_Type: auto # If enabled the backpack will be saved regardless of if there have been changes to it or not. This will slightly negatively impact performance. # This will help with changes made to items inside the backpack by other plugins. For example plugins that allow you to interact with items, when you allow your players to store these items inside the backpack. ForceSaveOnUnload: false # Settings only for MySQL SQL: Host: "localhost:3306" Database: "minecraft" User: "minecraft" Password: "minecraft" # The max amount of connections to the database the connection pool will open MaxConnections: 2 # Sets the max lifetime of the connection in seconds. -1 = Default (30min) MaxLifetime: -1 # Sets the idle timeout of the connection in seconds. -1 = Default (15min) IdleTimeout: -1 # List of properties for your SQL connection. Can be used to disable SSL. # Properties: ["useSSL=false"] Properties: [] # Tables settings for shared tables when using MySQL - Advanced MySQL Settings # Use these settings only if you know what you are doing!!!! # Do only change these settings if you know what you are doing and have some basic MySQL knowledge!!! # Changing settings down here after you have used this plugin may result in data inconsistency!!! Tables: # Table names # Don't change the players table if you have backpacks stored in your database already! Player id's might not match any more resulting data inconsistency. User: backpack_players Backpack: backpacks Cooldown: backpack_cooldowns # Field settings for the tables # Do not change them after the tables have been generated! # If you like to change them after the tables have been generated alter the tables manually or delete them (the system then will regenerate them). Fields: User: Player_ID: player_id Name: name UUID: uuid Backpack: Owner_ID: owner ItemStacks: itemstacks Version: version LastUpdate: lastupdate Cooldown: Player_ID: id Time: time # Settings controlling the cache behavior of the plugin. You may optimize it a little depending on your player count, ram or cpu bottlenecks. Cache: UnCache: # The strategy used to uncache offline players. Options # interval (offline players get uncached every x seconds) # intervalChecked (like interval, but also ensures that the player is already offline for at least the interval time, adds a cpu overhead) # ondisconnect (player instantly gets uncached as soon as he disconnects, may adds overhead if other plugins try to access the player data when they go offline, also it may be problematic for players with unstable connections) # ondisconnectdelayed (player gets uncached x seconds after he went offline, adds overhead on disconnect, you shouldn't use this with a lot of players joining and leaving.) Strategy: interval # Used for the interval based uncaching algorithms, and is also used as delay for ondisconnectdelayed. Value in seconds. Default: 600 = 10 minutes Interval: 600 Delay: 600 Shulkerboxes: # This setting controls whether players can put shulkerboxes into their backpacks. PreventInBackpack: true # This setting allows disabling shulkerboxes all together. Players won't be able to craft or use them. DisableShulkerboxes: false # This setting controls how existing shulkerboxes are handled if they are disabled. # Options: Ignore, Remove = shulker-box will be removed including its content, Destroy = shulker-box will be destroyed, and it's content will be dropped Existing: "Ignore" ItemFilter: # Enables the item filter. Make sure to define items to be filtered. Enabled: false # Changes the filter mode, either blacklist (only unlisted materials are allowed) or whitelist (only listed materials are allowed) Mode: blacklist # Filter lists bellow. An item will be blocked (in blacklist mode) or allowed (in whitelist mode) if it matches on of the given filters. # List of materials that should be filtered. Can be name or id (id only for MC versions older than 1.13!). Materials: [] # List of names that should be filtered. Must match the display name of the item exactly. & color codes will be converted automatically. Names: [] # List of lore that should be filtered. Can be a single line or all lines of the lore. Lore: [] # These settings allow control over how the plugin behave in different worlds WorldSettings: # Options: blacklist (all worlds listed in FilteredWorlds will be blocked), whitelist (all worlds listed in FilteredWorlds will be allowed) FilterType: "blacklist" # All worlds listed here will not have the plugin usable # FilteredWorlds: ["creative_world"] # FilteredWorlds: ["creative_world1", "creative_world2"] FilteredWorlds: [] # Defines how the Blacklist will be enforced # Options: # Message = The player will see a message that the usage of the backpack is not allowed in this world. # MissingPermission = The player will receive the plugins no permission message. # NoPlugin = The plugin will not be available at all and act as if it was not installed. # This also exclude players with permission to bypass the world restriction from using it! # It will not disable the Shulkerboxes filter! BlockMode: "Message" # Gives the players an item they can interact with to open their backpack. Only works on MC 1.8 or newer. ItemShortcut: # If enabled the players will be given an item they can interact with to open the backpack. # The item may not be removed from their inventory as long as this option is enabled. Enabled: true # The name of the item in the inventory ItemName: "&eBackpack" # The texture value for the head. # Heads can be found here: https://minecraft-heads.com/custom-heads/ # The correct value is the one listed on the head page under Other/Value HeadTextureValue: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGRjYzZlYjQwZjNiYWRhNDFlNDMzOTg4OGQ2ZDIwNzQzNzU5OGJkYmQxNzVjMmU3MzExOTFkNWE5YTQyZDNjOCJ9fX0=" # Increases compatibility with some death chest plugins. Enable this if the backpack item gets added to your death chest! # Please note: This will not move items from the backpack to the death chest! The items in the backpack will still drop to the ground unless DropOnDeath is disabled. ImproveDeathChestCompatibility: false # Prevents the backpack from being used as a hat BlockAsHat: false # Opens a container if right-clicked while holding the backpack shortcut in the hand. This option will only work on MC 1.13 or newer. OpenContainerOnRightClick: false # The id of the slot that should be preferred when giving a player the shortcut item PreferredSlotId: -1 # If this option is enabled the player will not be able to move the backpack item within their inventory BlockItemFromMoving: false Sound: # Enables all sound effects Enabled: true # The sound effect that should be played when the backpack is opened # disabled or false to disable the sound effect # auto will play the chest sound for minecraft versions older than 1.11, and the shulker-box sound for newer MC versions OpenSound: auto # The sound effect that should be played when the backpack is closed # disabled or false to disable the sound effect # auto will play the chest sound for minecraft versions older than 1.11, and the shulker-box sound for newer MC versions CloseSound: auto # Settings for the inventory management InventoryManagement: ClearCommand: # If enabled the plugin provides an inventory clear command that keeps the backpack item. Enabled: true Misc: AutoUpdate: # When auto update is disabled you still can use the build in update function manually with /backpack update Enabled: true Channel: ${updateChannel} # Enable this option if you are using a BungeeCord setup and want to share the plugin's database across multiple servers. UseBungeeCord: false # Config file version. Don't touch it! Version: ${configFileVersion} ================================================ FILE: Minepacks/resources/lang/chs.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "§f[§b背包§f] 控制台无法执行这个命令。" Ingame: NoPermission: "§f[§b背包§f] 您没有权限。" WorldDisabled: "§f[§b背包§f] 这个世界禁用。" NaN: "§f[§b背包§f] 无效的数值。" OwnBackpackClose: "§f[§b背包§f] 背包关闭" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "§f[§b背包§f] 玩家 §a{OwnerName} §f背包关闭。" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "§f[§b背包§f] 无效的背包。" NotAllowedInBackpack: "§f[§b背包§f] 物品 {ItemName} §f不能放背包内。" NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "§f[§b背包§f] 您不能从背包丢弃头颅。" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "§f[§b背包§f] 您的背包缩小了!一些物品掉到了地上!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "§f[§b背包§f] 请等待 §e{TimeLeft} §f秒。" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "§f[§b背包§f] 您不能在这种游戏模式下打开背包。" Clean: BackpackCleaned: "§f[§b背包§f] 背包清空。" BackpackCleanedBy: "§f[§b背包§f] 玩家 {DisplayName} 清空您的背包。" BackpackCleanedOther: "§f[§b背包§f] 玩家 {DisplayName} 的背包已清空。" Sort: Sorted: "§f[§b背包§f] 背包分类" Help: Header: "" Footer: "" Reload: Reloading: "§f[§b背包§f] 重新加载中" Reloaded: "§f[§b背包§f] 更新配置与语言文件" Update: CheckingForUpdates: "§f[§b背包§f] 检查更新" Updated: "§f[§b背包§f] 插件已更新,将在下次启动加载。" NoUpdate: "§f[§b背包§f] 没有可用的更新。" UpdateFail: "§f[§b背包§f] 出现错误!请检查控制台!" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "§f[§b背包§f] 发现新版本 https://www.spigotmc.org/resources/19286/" Backup: Created: "§f[§b背包§f] 背包已备份" NoBackpack: "§f[§b背包§f] 玩家没有背包,或者背包是空的。" Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"showing page {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Previous <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Showing page {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Next >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "No backup matching {BackupIdentifier} found" NoUserToRestoreToFound: "No valid user to restore backup to found" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Backup has been successful restored." InventoryClear: UnknownPlayer: "&c找不到玩家 {Name}!" Cleared: "物品栏已清空。" ClearedOther: "{DisplayName}&r 的物品栏已清空。" ClearedOtherTarget: "您的物品栏已被 {DisplayName}&r 清空。" Pickup: ToggleOn: "&7自动物品收集已切换为 &a开&7。" ToggleOff: "&7自动物品收集已切换为 &c关&7。" Commands: HelpFormat: "§f[§b背包§f] {Description}命令 “/{MainCommand} {SubCommand} {Parameters}”" PlayerNameVariable: "player_name" Description: Backpack: "打开背包" Sort: "整理背包" Clean: "清空背包" CleanOthers: "清空玩家背包" OpenOthers: "显示玩家背包" Reload: "重新加载" Update: "检查更新" Version: "查看版本" Backup: "创建备份" BackupEveryone: "为目前所有在线的玩家创建备份。" Restore: "打开备份" RestoreList: "列出所有备份" Help: "查看帮助" Migrate: "迁移数据类型" Pickup: "当物品栏已满时切换自动拾取状态。" Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "中文" Author: "尹" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/cht.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&c後台將無法使用此指令!" Ingame: NoPermission: "&c您沒有足夠的權限去使用此指令!" WorldDisabled: "&c此世界不允許玩家存取隨身背包!" NaN: "您所輸入的數值無效!" OwnBackpackClose: "已關閉隨身背包" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} 的隨身背包已關閉" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "&c無效的隨身背包!" NotAllowedInBackpack: "&c{ItemName} 不被允許在此背包中!" NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&c您不能從背包中刪除快捷方式!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&c您的背包縮小了!一些物品掉到了地上!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "&e請等待 {TimeLeft} 秒再使用該指令" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "&c您將不被允許在此模式中開啟背包!" Clean: BackpackCleaned: "&e該隨身背包將已被清空~" BackpackCleanedBy: "&e您的隨身背包已被 {DisplayName} &e清空~" BackpackCleanedOther: "&c{DisplayName} &e的背包已被清空~" Sort: Sorted: "該隨身背包已分類" Help: Header: "&e----- &6隨身背包 指令列表 &e-----" Footer: "" Reload: Reloading: "&6背包插件重載中!" Reloaded: "&a已成功重載背包配置~" Update: CheckingForUpdates: "&e可用的更新檢查中..." Updated: "插件已更新" NoUpdate: "[\"\",{\"text\":\"No plugin update available.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"There was a problem looking for updates! Please check the console!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"There is an update available! Please go to \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" to download it!\"}]" Backup: Created: "The backpack has been backed up successful." NoBackpack: "The player doesn't have a backpack or his backpack is empty." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"showing page {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Previous <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Showing page {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Next >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "No backup matching {BackupIdentifier} found" NoUserToRestoreToFound: "No valid user to restore backup to found" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Backup has been successful restored." InventoryClear: UnknownPlayer: "&c找不到玩家 {Name}!" Cleared: "物品欄已清空。" ClearedOther: "{DisplayName}&r 的物品欄已清空。" ClearedOtherTarget: "您的物品欄已被 {DisplayName}&r 清空。" Pickup: ToggleOn: "&7自動物品收集已切換為 &a開&7。" ToggleOff: "&7自動物品收集已切換為 &c關&7。" Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "開啟您的隨身背包" Sort: "整理您的隨身背包" Clean: "清空您的隨身背包" CleanOthers: "清空其他玩家的隨身背包" OpenOthers: "顯示其他玩家的隨身背包" Reload: "重載插件配置設定" Update: "檢查可用的更新" Version: "查看此插件的版本" Backup: "建立一個新的備份" BackupEveryone: "為目前所有在線的玩家建立備份。" Restore: "回復備份" RestoreList: "所有已備份的列表" Help: "查看所有指令的幫助" Migrate: "轉移玩家的隨身背包" Pickup: "當物品欄已滿時切換自動拾取狀態。" Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "繁體中文" Author: "Umekaw" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/cz.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cTento příkaz nelze použít z konzole." Ingame: NoPermission: "&cNa toto nemáš dostatečná oprávnění!" WorldDisabled: "&cPoužití batohu není v tomto světě povoleno." NaN: "[\"\",{\"text\":\"Zadaná hodnota není číslo!\",\"color\":\"red\"}]" OwnBackpackClose: "Batoh byl zavřen!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "Batoh hráče {OwnerName} byl zavřen!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Neplatný batoh." NotAllowedInBackpack: "&c{ItemName} není v batohu povoleno." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cNesmíš odstranit zkratku batohu ze svého inventáře!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cTvůj batoh se zmenšil! Některé předměty spadly na zem!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Počkej prosím \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} sekund\"}},{\"text\":\" než znovu otevřeš svůj batoh.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Nemáš oprávnění otevřít svůj batoh v aktuálním herním módu." Clean: BackpackCleaned: "Batoh byl vyčištěn." BackpackCleanedBy: "Tvůj batoh byl vyčištěn hráčem {DisplayName}&r." BackpackCleanedOther: "Batoh hráče {DisplayName}&r byl vyčištěn." Sort: Sorted: "Batoh byl seřazen." Help: Header: "&6### Minepacks Příkazy ###" Footer: "&6#############################" Reload: Reloading: "&1Znovu načítám Minepacks ..." Reloaded: "&1Minepacks znovu načten!" Update: CheckingForUpdates: "&1Kontroluji aktualizace ..." Updated: "[\"\",{\"text\":\"Plugin aktualizován, bude načten při příštím restartu/reloadu.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Žádná aktualizace pluginu není k dispozici.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Nastal problém při hledání aktualizací! Zkontroluj konzoli!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Je k dispozici aktualizace! Jdi na \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" pro stažení!\"}]" Backup: Created: "Batoh byl úspěšně zálohován." NoBackpack: "Hráč nemá batoh nebo je jeho batoh prázdný." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Zálohy\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"zobrazena stránka {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Předchozí <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Zobrazena stránka {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Další >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Uživatel: {BackupPlayerName} ({BackupPlayerUUID})\\nVytvořeno: {BackupDate}\"}}]" NoValidBackup: "Žádná záloha odpovídající {BackupIdentifier} nenalezena" NoUserToRestoreToFound: "Žádný platný uživatel pro obnovení zálohy nenalezen" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Záloha byla úspěšně obnovena." InventoryClear: UnknownPlayer: "&cHráče {Name} se nepodařilo najít!" Cleared: "Inventář vyčištěn." ClearedOther: "Inventář hráče {DisplayName}&r byl vyčištěn." ClearedOtherTarget: "Tvůj inventář byl vyčištěn hráčem {DisplayName}&r." Pickup: ToggleOn: "&7Automatický sběr předmětů byl &aZAPNUT&7." ToggleOff: "&7Automatický sběr předmětů byl &cVYPNUT&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Otevře tvůj batoh." Sort: "Seřadí tvůj batoh." Clean: "Vyčistí tvůj batoh." CleanOthers: "Vyčistí batoh jiného hráče." OpenOthers: "Zobrazí batoh jiného hráče." Reload: "Znovu načte konfiguraci pluginu." Update: "Zkontroluje nové aktualizace pluginu." Version: "Vypíše detaily o verzi pluginu a jeho závislostech." Backup: "Vytvoří zálohu batohu hráče." BackupEveryone: "Vytvoří zálohu pro všechny, kteří jsou momentálně online." Restore: "Obnoví zálohu." RestoreList: "Vypíše všechny dostupné zálohy." Help: "Zobrazí všechny dostupné příkazy a jejich popis." Migrate: "Převede používanou databázi z jednoho typu na jiný." Pickup: "Přepne stav automatického sběru, když je inventář plný." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "czech" Author: "ProPl4yerCz" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/de.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cDieser Befehl kann nicht in der Konsole ausgeführt werden." Ingame: NoPermission: "&cDir fehlen die Rechte dafür." NaN: "[\"\",{\"text\":\"Die Eingabe ist keine gültige Zahl!\",\"color\":\"red\"}]" WorldDisabled: "&cDie Verwendung des Rucksacks ist in dieser Welt deaktiviert!" OwnBackpackClose: "Rucksack geschlossen." OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName}'s Rucksack geschlossen." PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Rucksack fehlerhaft." NotAllowedInBackpack: "&c{ItemName} ist im Rucksack nicht erlaubt." DontRemoveShortcut: "&cDu darfst den Rucksack nicht aus deinem Inventar entfernen!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cDein Rucksack ist geschrumpft! Einige Items sind auf den Boden gefallen!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Bitte warte \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} Sekunden\"}},{\"text\":\" bis du deinen Rucksack wieder öffnest.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Du darfst deinen Rucksack in deinem aktuellem Gamemode nicht öffnen." Clean: BackpackCleaned: "Rucksack geleert." BackpackCleanedBy: "Dein Rucksack wurde von {DisplayName}&r geleert" BackpackCleanedOther: "Der Rucksack von {DisplayName}&r wurde geleert." Sort: Sorted: "Dein Rucksack wurde sortiert." Help: Header: "&6### Minepacks Commands ###" Footer: "&6#############################" Reload: Reloading: "&Minepacks wird neu geladen ..." Reloaded: "&1Minepacks neu geladen!" Update: CheckingForUpdates: "&1Suche nach Aktualisierungen ..." Updated: "[\"\",{\"text\":\"Plugin wurde aktualisiert, Änderungen werden mit dem nächsten Neustart übernommen.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Plugin-Aktualisierung verfügbar.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Es gab ein Problem bei der Suche nach Updates! Bitte prüfe den Log für mehr Details.\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Es ist eine Aktualisierung verfügbar! Bitte gehe auf \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" um es herunter zu laden!\"}]" Backup: Created: "Rucksack wurde gesichert." NoBackpack: "Der Spieler hat keinen Rucksack oder keine Items in seinem Rucksack." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"Seite {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Vorherige <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Seite {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Nächste >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nErstellt: {BackupDate}\"}}]" NoValidBackup: "{BackupIdentifier} ist kein gültiges Backup" NoUserToRestoreToFound: "Kein gültiger Nutzer zum Wiederherstellen gefunden" # NoJSON ParameterBackupName: "backup_name" # No Json!!! DateFormat: "dd.MM.yyyy HH:mm:ss" Restored: "Backup wurde erfolgreich wiederhergestellt." InventoryClear: UnknownPlayer: "&cSpieler {Name} konnte nicht gefunden werden!" Cleared: "Inventar gelöscht." ClearedOther: "Das Inventar von {DisplayName}&r wurde gelöscht." ClearedOtherTarget: "Dein Inventar wurde von {DisplayName}&r gelöscht." Pickup: ToggleOn: "&7Automatisches Itemsammeln wurde &aEINGESCHALTET&7." ToggleOff: "&7Automatisches Itemsammeln wurde &cAUSGESCHALTET&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Öffnet deinen Rucksack." Sort: "Sortiert deinen Rucksack" Clean: "Leert deinen Rucksack." CleanOthers: "Leert den Rucksack eines anderen Spielers." OpenOthers: "Öffnet den Rucksack eines anderen Spielers." Reload: "Lädt die Konfigurationsdatei neu." Update: "Prüft auf neue Plugin-Updates." Backup: "Erstellt eine Sicherungskopie eines Rucksacks." BackupEveryone: "Erstellt eine Sicherungskopie der Rucksäcke aller verbundenen Spieler." Restore: "Stellt eine Sicherungskopie eines Rucksacks wieder her." RestoreList: "Listet alle verfügbaren Sicherungskopien von Rucksäcken auf." Version: "Gibt die Versionsdetails über das Plugin und seine Abhängigkeiten aus." Help: "Zeigt die verfügbaren Befehle an." Migrate: "Erlaubt das Konvertieren der Datenbank in ein anderes Format." Pickup: "Schaltet den automatischen Item-Aufnahmestatus um, wenn das Inventar voll ist." Command: Backpack: - backpack - bp - rucksack Open: - open - öffnen Sort: - sort - sortieren Clean: - clean - clear - empty - leeren - löschen Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help - hilfe InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "german" Author: "GeorgH93" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/en.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cCommand not usable from console." Ingame: NoPermission: "&cYou don't have the permission to do that." WorldDisabled: "&cThe use of the backpack is not allowed in this world." NaN: "[\"\",{\"text\":\"The entered value is not a number!\",\"color\":\"red\"}]" OwnBackpackClose: "Backpack closed!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName}'s backpack closed!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Invalid backpack." NotAllowedInBackpack: "&c{ItemName} is not allowed in the backpack." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cYou must not remove the backpack shortcut from your inventory!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cYour backpack shrunk! Some items fell to the ground!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Please wait \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} seconds\"}},{\"text\":\" till you reopen your backpack.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "You are not allowed to open your backpack in your current game-mode." Clean: BackpackCleaned: "Backpack cleared." BackpackCleanedBy: "Your backpack has been cleared by {DisplayName}&r." BackpackCleanedOther: "{DisplayName}'s&r backpack has been cleared." Sort: Sorted: "Backpack sorted." Help: Header: "&6### Minepacks Commands ###" Footer: "&6#############################" Reload: Reloading: "&1Reloading Minepacks ..." Reloaded: "&1Minepacks reloaded!" Update: CheckingForUpdates: "&1Checking for updates ..." Updated: "[\"\",{\"text\":\"Plugin updated, will be loaded on next restart/reload.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"No plugin update available.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"There was a problem looking for updates! Please check the console!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"There is an update available! Please go to \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" to download it!\"}]" Backup: Created: "The backpack has been backed up successfully." NoBackpack: "The player doesn't have a backpack or his backpack is empty." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"showing page {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Previous <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Showing page {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Next >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "No backup matching {BackupIdentifier} found" NoUserToRestoreToFound: "No valid user to restore backup to found" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Backup has been successfully restored." InventoryClear: UnknownPlayer: "&cCould not find player {Name}!" Cleared: "Inventory cleared." ClearedOther: "{DisplayName}'s&r inventory has been cleared." ClearedOtherTarget: "Your inventory has been cleared by {DisplayName}&r." Pickup: ToggleOn: "&7Automatic item collection has been toggled &aON&7." ToggleOff: "&7Automatic item collection has been toggled &cOFF&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Opens your backpack." Sort: "Sorts your backpack." Clean: "Cleans your backpack." CleanOthers: "Cleans the backpack of another player." OpenOthers: "Shows the backpack of another player." Reload: "Reloads the config of the plugin." Update: "Checks for new plugin updates." Version: "Prints the version details about the plugin and its dependencies." Backup: "Creates a backup of a player's backpack." BackupEveryone: "Creates a backup of everyone currently online." Restore: "Restores a backup." RestoreList: "Lists all available backups." Help: "Shows all available commands and their description." Migrate: "Migrates the used database from one type to another." Pickup: "Toggle the state of the automatic pickup when the inventory is full." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "english" Author: "GeorgH93" # Language file version. Don't touch it! Version: ${languageFileVersion} ================================================ FILE: Minepacks/resources/lang/es.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cEl comando no puede ser usado desde la consola." Ingame: NoPermission: "&cNo tienes permiso para hacer esto." WorldDisabled: "&cEl uso de las mochilas no está permitido en este mundo." NaN: "[\"\",{\"text\":\"¡El valor introducido no es un número!\",\"color\":\"red\"}]" OwnBackpackClose: "¡Mochila cerrada!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "¡La mochila de {OwnerName} fue cerrada!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Mochila no válida" NotAllowedInBackpack: "&cNo está permitido almacenar el item {ItemName} en la mochila." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cNo puedes remover la mochila de tu hotbar o inventario!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&c¡Tu mochila se ha encogido! ¡Algunos objetos cayeron al suelo!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Por favor, espera \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} segundos\"}},{\"text\":\" hasta que vuelvas a abrir tu mochila.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "No está permitido acceder a las mochilas en tu modo de juego actual." Clean: BackpackCleaned: "Mochila vaciada" BackpackCleanedBy: "Su mochila ha sido despejada por {DisplayName}&r." BackpackCleanedOther: "La mochila de {DisplayName}&r ha sido despejada." Sort: Sorted: "Mochila organizada." Help: Header: "&6### Comandos Minepacks ###" Footer: "&6#############################" Reload: Reloading: "&1Actualizando..." Reloaded: "&1¡Actualizado!" Update: CheckingForUpdates: "&cComprobando actualizaciones..." Updated: "[\"\",{\"text\":\"Plugin actualizado, será cargado en el siguiente reinicio/parada.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"No hay actualización del plugin disponible.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"¡Hubo un error comprando actualizaciones! ¡Por favor, revisa la consola!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"¡Hay una actualización disponible! ¡Por favor, ve a \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" para descargarla!\"}]" Backup: Created: "La mochila fue respaldada con éxito." NoBackpack: "El jugador no tiene mochila o se encuntra vacia." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"mostrando pág. {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Anterior <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Mostrando pág. {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Siguiente >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreado: {BackupDate}\"}}]" NoValidBackup: "No se encontraron coincidencias con el backup {BackupIdentifier}." NoUserToRestoreToFound: "Usuario no valido para restaurar la copia de seguridad." # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "La mochila fue restaurada correctamente." InventoryClear: UnknownPlayer: "&cNo se ha podido encontrar al jugador {Name}!" Cleared: "Inventario despejado." ClearedOther: "El inventario de {DisplayName}&r ha sido despejado." ClearedOtherTarget: "Tu inventario ha sido despejado por {DisplayName}&r." Pickup: ToggleOn: "&7La recolección automática de objetos ha sido &aACTIVADA&7." ToggleOff: "&7La recolección automática de objetos ha sido &cDESACTIVADA&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Abre tu mochila." Sort: "Ordena tu mochila." Clean: "Vacia tu mochila." CleanOthers: "Vacia la mochila de otro jugador." OpenOthers: "Observa la mochila de otro jugador." Reload: "Actualiza la configuración del plugin." Update: "Comprueba las nuevas actualizaciones del plugin." Version: "Imprime los detalles de la versión del plugin y sus dependencias." Backup: "Crea un backup de la mochila de un jugador." BackupEveryone: "Crea una copia de seguridad de todos los que están conectados en ese momento." Restore: "Restaura una mochila." RestoreList: "Lista de todas las mochilas disponibles." Help: "Muestra todos los comandos disponibles y sus descripciones." Migrate: " Migra la base de datos utilizada de un tipo a otro." Pickup: "Alterna el estado de la recolección automática cuando el inventario está lleno." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "es_es" Author: "ThatOverPowered & PostBoxRetinal" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/fr.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cCommande inutilisable depuis la console." Ingame: NoPermission: "&cVous n'avez pas la permission !" WorldDisabled: "&cL'utilisation du sac à dos n'est pas autorisée dans ce monde." NaN: "[\"\",{\"text\":\"La valeur saisie n'est pas un nombre !\",\"color\":\"red\"}]" OwnBackpackClose: "Sac à dos fermé !" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} sac à dos fermé !" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Sac à dos non valide." NotAllowedInBackpack: "&c{ItemName} n'est pas autorisé dans le sac à dos." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cVous ne devez pas supprimer le raccourci de sac à dos de votre inventaire !" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cVotre sac à dos a rétréci ! Certains objets sont tombés au sol !" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Veuillez patienter \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} secondes\"}},{\"text\":\" till you reopen your backpack.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Vous n'êtes pas autorisé à ouvrir votre sac à dos dans votre mode de jeu actuel." Clean: BackpackCleaned: "Sac à dos nettoyé." BackpackCleanedBy: "Votre sac à dos à été nettoyé par {DisplayName}&r." BackpackCleanedOther: "Sac à dos de {DisplayName} &rnettoyé." Sort: Sorted: "Sac à dos trié." Help: Header: "&6### Minepacks Commandes ###" Footer: "&6#############################" Reload: Reloading: "&1Le plugin est en cours de redémarrage ..." Reloaded: "&1Le plugin à été rechargé !" Update: CheckingForUpdates: "&1Vérification des mises à jour ..." Updated: "[\"\",{\"text\":\"Plugin mis à jour, sera chargé au prochain redémarrage/rechargement.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Aucune mise à jour du plugin disponible.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Il y a eu un problème de recherche de mises à jour ! Vérifiez la console s'il vous plaît !\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Il y a une mise à jour disponible ! Veuillez vous rendre à l'adresse suivante \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" pour la télécharger !\"}]" Backup: Created: "Le sac à dos a été sauvegardé avec succès." NoBackpack: "Le joueur n'a pas de sac à dos ou son sac à dos est vide." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"Page {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Previous <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Page {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Next >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Utilisateur: {BackupPlayerName} ({BackupPlayerUUID})\\nCréé: {BackupDate}\"}}]" NoValidBackup: "Aucune correspondance des sauvegardes {BackupIdentifier} trouvé." NoUserToRestoreToFound: "Aucun utilisateur valide pour restaurer la sauvegarde sur trouvée" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "dd.MM.yyyy HH:mm:ss" Restored: "La sauvegarde a été restaurée avec succès." InventoryClear: UnknownPlayer: "&cImpossible de trouver le joueur {Name}!" Cleared: "Inventaire nettoyé." ClearedOther: "Inventaire de {DisplayName} &rnettoyé." ClearedOtherTarget: "Votre inventaire a été effacé par {DisplayName}&r." Pickup: ToggleOn: "&7Le ramassage automatique à été défini sur: &aON&7." ToggleOff: "&7Le ramassage automatique à été défini sur: &cOFF&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Ouvre votre sac à dos." Sort: "Trie votre sac à dos." Clean: "Nettoie votre sac à dos." CleanOthers: "Nettoie le sac à dos d'un autre joueur." OpenOthers: "Montre le sac à dos d'un autre joueur." Reload: "Recharge la configuration du plugin." Update: "Vérifie les nouvelles mises à jour des plugins." Version: "Imprime les détails de la version du plugin et de ses dépendances." Backup: "Crée une sauvegarde d'un sac à dos de joueur." BackupEveryone: "Crée une backup de tout les backpacks." Restore: "Restaure une sauvegarde." RestoreList: "Liste toutes les sauvegardes disponibles." Help: "Affiche toutes les commandes disponibles et leur description." Migrate: "Migre la base de données utilisée d'un type à un autre." Pickup: "Switch l'état de ramassage automatique (ON/OFF)." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "Français" Author: "HiiRaZ & Sniper_TVmc" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/hu.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cA parancs nem használható konzolból." Ingame: NoPermission: "&cNincs jogod ezt megtenni." WorldDisabled: "&cA hátizsák használata nem engedélyezett ebben a világban." NaN: "[\"\",{\"text\":\"A beírt érték nem egy szám!\",\"color\":\"red\"}]" OwnBackpackClose: "Hátizsák bezárva!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} hátizsákja bezárva!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Érvénytelen hátizsák." NotAllowedInBackpack: "&c{ItemName} nem engedélyezett a hátizsákban." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cNem szabad eltávolítani a hátizsák ikonját az eszköztárból!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cA hátizsákod összement! Néhány tárgy a földre esett!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Várj \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} másodperc\"}},{\"text\":\", amíg újra nem nyitja a hátizsákot.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "A jelenlegi játékmódban nem engedélyezett kinyitni a hátizsákot." Clean: BackpackCleaned: "Hátizsák kitisztítva." BackpackCleanedBy: "A hátizsákodat {DisplayName}&r tisztította ki." BackpackCleanedOther: "{DisplayName}&r hátizsákja ki lett tisztítva." Sort: Sorted: "Hátizsák rendezve." Help: Header: "&6### Minepacks parancsok ###" Footer: "&6#############################" Reload: Reloading: "&1Minepacks újratöltése ..." Reloaded: "&1Minepacks újratöltve!" Update: CheckingForUpdates: "&1Frissítések ellenőrzése ..." Updated: "[\"\",{\"text\":\"Plugin frissítve, be lesz töltve a következő újraindítás/újratöltésnél.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Nincs plugin frissítés elérhető.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Probléma volt a frissítések keresésekor! Kérlek, ellenőrizd a konzolt!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Van egy frissítés elérhető! Menj a(z) \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\", hogy letöltsd!\"}]" Backup: Created: "A hátizsák sikeresen mentésre került." NoBackpack: "A játékosnak nincs egy hátizsákja vagy a hátizsákja üres." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Mentések\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"oldal {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Előző <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Oldal {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Következő >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Felhasználó: {BackupPlayerName} ({BackupPlayerUUID})\\nLétrehozva: {BackupDate}\"}}]" NoValidBackup: "Nincs mentés találva {BackupIdentifier}" NoUserToRestoreToFound: "Nincs érvényes felhasználó, aki visszaállíthatja a biztonsági másolatot" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Biztonsági mentés sikeresen visszaállítva." InventoryClear: UnknownPlayer: "&cNem található a játékos {Name}!" Cleared: "Leltár törölve." ClearedOther: "{DisplayName}&r leltára törölve lett." ClearedOtherTarget: "A leltárodat {DisplayName}&r törölte." Pickup: ToggleOn: "&7Az automatikus tárgyfelvétel &aBEKAPCSOLVA&7." ToggleOff: "&7Az automatikus tárgyfelvétel &cKIKAPOCSOLVA&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Megnyitja a hátizsákod." Clean: "Törli a hátizsákod." CleanOthers: "Törli más játékosok hátizsákját." OpenOthers: "Megmutatja más játékosok hátizsákját." Reload: "Újratölti a konfigot és a plugint." Update: "Ellenőrzi a plugin új frissítéseit." Version: "Kiírja a plugin verziójának részleteit és annak függőségeit." Backup: "Létrehoz egy mentést a játékosok hátizsákjáról." BackupEveryone: "Biztonsági mentést készít minden jelenleg online lévő személyről." Restore: "Visszaállít egy mentést." RestoreList: "Listázza az összes elérhető mentéseket." Help: "Megmutatja az összes elérhető parancsokat és azok leírását." Migrate: "A használt adatbázist áttelepíti egyik típusról a másikra." Pickup: "Átváltja az automatikus felvétel állapotát, ha a leltár tele van." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "hungarian" Author: "montlikadani" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/it.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cComando non utilizzabile dalla console." Ingame: NoPermission: "&cPermesso negato." WorldDisabled: "&cL'uso dei backpack non è autorizzato in questo mondo." NaN: "[\"\",{\"text\":\"Il valore inserito non è un numero!\",\"color\":\"red\"}]" OwnBackpackClose: "Backpack chiuso!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "Backpack di {OwnerName} chiuso!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Backpack invalido." NotAllowedInBackpack: "&c{ItemName} non può essere inserito nel backpack." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cNon puoi rimuovere il backpack dalla hotbar o inventario!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cIl tuo zaino si è ristretto! Alcuni oggetti sono caduti a terra!" Open: #Parameter: {TimeLeft} secondi per riaprire il backpack, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Perfavore aspettaret \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} secondi\"}},{\"text\":\" per riaprire il backpack.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Non puoi aprire il backpack in questa game-mode." Clean: BackpackCleaned: "Backpack svuotato." BackpackCleanedBy: "Il tuo backpack è stato svuotato da {DisplayName}&r." BackpackCleanedOther: "Il backpack di {DisplayName}&r è stato svuotato." Sort: Sorted: "Backpack organizzato." Help: Header: "&6### Comandi Minepacks ###" Footer: "&6#############################" Reload: Reloading: "&1Ricaricando Minepacks ..." Reloaded: "&1Minepacks ricaricati!" Update: CheckingForUpdates: "&1Cercando aggiornamenti ..." Updated: "[\"\",{\"text\":\"Plugin aggiornato, sarà caricato al prossimo riavvio/reload.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Nessun aggiornamento disponibile.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"C'è stato un problema per trovare gli aggiornamenti! Perfavore controllare la console!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"C'è un aggiornamento disponibile! Perfavore usa \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" per scaricarlo!\"}]" Backup: Created: "Backup del backpack eseguito con successo." NoBackpack: "Il giocatore non ha un backpack o è vuoto." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backup\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"pagina {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Precedente <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Pagina {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Prossimo >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Utente: {BackupPlayerName} ({BackupPlayerUUID})\\nData di creazione: {BackupDate}\"}}]" NoValidBackup: "Nessun backup per {BackupIdentifier} trovato" NoUserToRestoreToFound: "Nessun utente valido per il backup trovato" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Il backup è stato ripristinato con successo." InventoryClear: UnknownPlayer: "&cImpossibile trovare l'utente {Name}!" Cleared: "Inventario ripulito." ClearedOther: "L'inventario di {DisplayName}&r è stato ripulito." ClearedOtherTarget: "Il tuo inventario è stato ripulito da {DisplayName}&r." Pickup: ToggleOn: "&7La raccolta automatica degli oggetti è stata &aATTIVATA&7." ToggleOff: "&7La raccolta automatica degli oggetti è stata &cDISATTIVATA&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Apre il tuo backpack." Sort: "Organizza il tuo backpack." Clean: "Ripulisce il tuo backpack." CleanOthers: "Ripulisce il backpack di un altro utente." OpenOthers: "Mostra il backpack di un altro utente." Reload: "Reicarica il plugin." Update: "Controlla per nuovi aggiornamenti." Version: "Mostra la versione del plugin e le sue relative dipendenze." Backup: "Crea un backup del backpack dell'utente." BackupEveryone: "Crea un backup di tutti gli utenti attualmente online." Restore: "Ripristina un backup." RestoreList: "Mostra tutti i backup disponibili." Help: "Mostra tutti i comandi disponibili e le loro descrizioni." Migrate: "Migra il database da un utente all'altro." Pickup: "Attiva/disattiva la raccolta automatica quando l'inventario è pieno." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "italiano" Author: "Mastory_Md5" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/ja.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cコマンドはコンソールから使用できません。" Ingame: NoPermission: "&cそれを実行する権限がありません。" WorldDisabled: "&cこのワールドでバックパックの使用は許可されていません。" NaN: "[\"\",{\"text\":\"入力された値は数値ではありません。\",\"color\":\"red\"}]" OwnBackpackClose: "バックパックを閉じました!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName}のバックパックを閉じました!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "バックパックが無効です。" NotAllowedInBackpack: "&c{ItemName}はバックパックに入れることができません。" NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cバックパックショートカットをインベントリから削除しないでください!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cバックパックが縮小しました!一部のアイテムが地面に落ちました!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "&2バックパックを開くまで{TimeSpanLeft}秒待ってください。" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "現在のゲームモードでバックパックを開くことは許可されていません。" Clean: BackpackCleaned: "バックパックを削除しました。" BackpackCleanedBy: "あなたのバックアップは{DisplayName}&rによって削除されました。" BackpackCleanedOther: "{DisplayName}&rのバックパックは削除されました。" Sort: Sorted: "バックパックがソートされました。" Help: Header: "&6##### Minepacks コマンド #####" Footer: "&6" Reload: Reloading: "&1リロード中..." Reloaded: "&1リロード!" Update: CheckingForUpdates: "&1アップデートの確認中..." Updated: "[\"\",{\"text\":\"更新されたプラグインは、次回の再起動/リロード時にロードされます。\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"利用可能なプラグインの更新はありません。\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"アップデートの確認に問題がありました!コンソールを確認してください。\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"利用可能なアップデートがあります!\\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" からダウンロードして下さい。\"}]" Backup: Created: "バックパックは正常にバックアップされました。" NoBackpack: "プレイヤーはバックパックを持っていないか、バックパックが空です。" Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"表示ページ {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< 前 <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" 表示ページ {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> 次 >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"ユーザー:{BackupPlayerName} ({BackupPlayerUUID})\\n作成日:{BackupDate}\"}}]" NoValidBackup: "{BackupIdentifier}に一致するバックアップが見つかりません" NoUserToRestoreToFound: "バックアップを復元するための有効なユーザーが見つかりません" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "バックアップは正常に復元されました。" InventoryClear: UnknownPlayer: "&c{Name}を見つけられませんでした!" Cleared: "インベントリが削除されました。" ClearedOther: "{DisplayName}&rのインベントリを削除しました。" ClearedOtherTarget: "あなたのインベントリは{DisplayName}&rによって削除されました。" Pickup: ToggleOn: "&7自動アイテム収集が&aオン&7になりました。" ToggleOff: "&7自動アイテム収集が&cオフ&7になりました。" Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "バックパックを開く。" Sort: "バックパックはソートされました。" Clean: "バックパックを削除する。" CleanOthers: "他のプレイヤーのバックパックを削除する。" OpenOthers: "他のプレイヤーのバックパックを開く。" Reload: "プラグインのコンフィグをリロードしました。" Update: "新しいアップデートを確認します。" Version: "プラグインと依存関係に関するバージョンの詳細を表示します。" Backup: "プレイヤーのバックパックのバックアップを作成します。" BackupEveryone: "現在オンラインの全員のバックアップを作成します。" Restore: "バックアップから復元します。" RestoreList: "利用可能なすべてのバックアップを一覧表示します。" Help: "利用可能なすべてのコマンドとその説明を表示します。" Migrate: "使用されているデータベースをあるタイプから別のタイプに移行しました。" Pickup: "インベントリがいっぱいの時の自動ピックアップの状態を切り替えます。" Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "japanese" Author: "ethernetcat" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/lt.yml ================================================ #Teisingam vertimui naudokite: https://ptp.pcgamingfreaks.at Use UTF8 instead Language: NotFromConsole: "&cKomanda negali būti naudojama konsolėje!" Ingame: NoPermission: "&cApgailestaujame, tačiau Jūs neturite tam leidimoĄ" WorldDisabled: "&cKuprinė negali būti naudojama šiame pasaulyje!" NaN: "[\"\",{\"text\":\"Įvestas skaičius nėra skaičius!\",\"color\":\"red\"}]" OwnBackpackClose: "Kuprinė uždaryta!" OwnBackpackClose_SendMethod: "action_bar" #Nustatymai: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} uždarė kuprinę!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Kuprinės klaida!" NotAllowedInBackpack: "&c{ItemName} draudžiama dėti į kuprinę!" NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cPrašome neišesti kuprinės iš savo inventoriaus!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cTavo kuprinė susitraukė! Kai kurie daiktai nukrito ant žemės!" Open: #Nustatymai: {TimeLeft} laikas kada vėl bus galima atidaryti, {TimeSpanLeft} laikas formatuotas kuprinės atidarymui Cooldown: "[{\"text\":\"Prašome palaukti \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} s\"}},{\"text\":\" kol vėl galėsite naudoti kuprinę!\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Najudojantis kūrybiniu rėžimu kuprine naudotis draudžiama!" Clean: BackpackCleaned: "Kuprinė išvalyta!" BackpackCleanedBy: "Jūsų kuprinę išvalė: {DisplayName}&r." BackpackCleanedOther: "{DisplayName} &r išvalė kuprinę1" Sort: Sorted: "Kuprinėje esantys daiktai surūšiuoti sėkmingai!" Help: Header: "&6### Kuprinių Komandos ###" Footer: "&6#############################" Reload: Reloading: "&1Perkraunamos kuprinės ..." Reloaded: "&1Kuprinė perkrautos!" Update: CheckingForUpdates: "&1Tikrinami kuprinių sistemos atnaujinimai ..." Updated: "[\"\",{\"text\":\"Kuprinių sistema atnaujinta, norint kad įsigaliotų sistemos pakeitimai privalote perkrauti serverį!\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Nėra kuprinių sistemos atnaujinimų, Jūs naudojate naujausią kuprinių sistemos versiją!\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Iškilo problema gaunat kuprinių sistemos atnaujinimų informaciją! Serverio klaida!\",\"color\":\"red\"}]" #Prašome neištrinti plugino sisteminio linko kitu atveju negausite update! UpdateAvailable: "[{\"text\":\"Kuprinių sistema turi atnaujinimą! Prašome nueiti į \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" ir parsisiūsti atnaujinimą!\"}]" Backup: Created: "Kuprinė išsaugota!" NoBackpack: "Žaidėjas neturi kuprinės, arba jo kuprinė tuščia!" Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Archyvas\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"showing page {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Ankst. <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Rodomas puslapis {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Kt. >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Žaidėjas: {BackupPlayerName} ({BackupPlayerUUID})\\nPridėta: {BackupDate}\"}}]" NoValidBackup: "No backup matching {BackupIdentifier} found" NoUserToRestoreToFound: "Nėra galimo atstatymo archyvo įrašuose!" #Ne sisteminis!!! ParameterBackupName: "backup_name" #Ne sisteminis!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Kuprinė buvo atstatyta iš archyvo!" InventoryClear: UnknownPlayer: "&cŽaidėjas: {Name} nerastas!" Cleared: "Inventorius išvalytas!" ClearedOther: "{DisplayName}&r išvalė inventorių!" ClearedOtherTarget: "Jūsų inventorių išvalė: {DisplayName}&r." Pickup: ToggleOn: "&7Automatinis daiktų rinkimas buvo &aĮJUNGTAS&7." ToggleOff: "&7Automatinis daiktų rinkimas buvo &cIŠJUNGTAS&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Atidarys kuprinę" Sort: "Surūšiuos daiktus kuprinėje" Clean: "Išvalys kuprinę" CleanOthers: "Išvalys kuprinę kitam žaidėjui" OpenOthers: "Atidarys kuprinę kitam žaidėjui" Reload: "Perkraus kuprinių sistemos nustatymus" Update: "Patikrins ar kuprinių sistema turi atnaujinimų" Version: "Parodys kuprinių sistemos esamą versijos aprašą" Backup: "Sukurs kuprinės įrašą archyve" BackupEveryone: "Sukurs visų šiuo metu prisijungusių žaidėjų atsarginę kopiją." Restore: "Atsatys kuprinę pagal įrašą archyve" RestoreList: "parodys archyvo įrašus" Help: "Parodys visas galimas kuprinių sistemos komandas" Migrate: "Perkels duomenų bazės įrašus nauju formatu" Pickup: "Perjungti automatinio rinkimo būseną, kai inventoriuje pilna." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup #Bus rodoma konsolėje starto metu! LanguageName: "lithuanian" Author: "Vyciokazz" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/nl.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cDit commando kan je niet vanuit de console gebruiken." Ingame: NoPermission: "&cJe bent niet gemachtigd om dat te doen." WorldDisabled: "&cHet gebruik van de rugzak is niet toegestaan in deze wereld." NaN: "[\"\",{\"text\":\"De ingevoerde waarde moet een getal zijn!\",\"color\":\"red\"}]" OwnBackpackClose: "Rugzak gesloten" OwnBackpackClose_SendMethod: "action_bar" # Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName}'s rugzak gesloten" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Ongeldige rugzak" NotAllowedInBackpack: "&c{ItemName} mag je niet in de rugzak bewaren." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cJe mag de rugzak niet uit je inventaris halen!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cJe rugzak is gekrompen! Sommige items zijn op de grond gevallen!" Open: # Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Wacht \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} seconds\"}},{\"text\":\" voordat je de rugzak heropent.\"}]" # Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "De rugzak mag in de huidige spelmodus niet worden geopend." Clean: BackpackCleaned: "Rugzak geleegd" BackpackCleanedBy: "Je rugzak is geleegd door {DisplayName}&r." BackpackCleanedOther: "{DisplayName}'s&r rugzak is geleegd." Sort: Sorted: "Rugzak gesorteerd." Help: Header: "&6### Minepacks Commando's ###" Footer: "&6#############################" Reload: Reloading: "&1Minepacks opnieuw laden" Reloaded: "&1Minepacks is herladen" Update: CheckingForUpdates: "&1Controleren op updates" Updated: "[\"\",{\"text\":\"Plugin geüpdatet, veranderingen zijn van kracht na de volgende herstart.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Geen plugin update beschikbaar.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Er was een probleem bij het zoeken naar updates. Bekijk de console!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Er is een update beschikbaar! Ga naar \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" om hem te downloaden!\"}]" Backup: Created: "De rugzak is succesvol opgeslagen." NoBackpack: "De speler heeft geen rugzak of deze is leeg." Restore: BackupsPerPage: "10" Headline: "[\"\",{\"text\":\"Back-ups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"Pagina {CurrentPage} van {MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Vorige <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Pagina {CurrentPage} van {MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Volgende >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "Geen back-up gevonden die overeenkomt met {BackupIdentifier}." NoUserToRestoreToFound: "Geen geldige speler gevonden waarbij de back-up kan worden hersteld." # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "d MMMM yyyy HH:mm[:ss]" Restored: "Back-up is succesvol hersteld." InventoryClear: UnknownPlayer: "&cKan speler {Name} niet vinden!" Cleared: "Inventaris geleegd" ClearedOther: "{DisplayName}'s&r inventaris is geleegd." ClearedOtherTarget: "Je inventaris is geleegd door {DisplayName}&r." Pickup: ToggleOn: "&7Automatische itemverzameling is &aAAN&7 gezet." ToggleOff: "&7Automatische itemverzameling is &cUIT&7 gezet." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Opent je rugzak." Sort: "Sorteert je rugzak." Clean: "Schoont je rugzak op." CleanOthers: "Schoont de rugzak op van andere spelers." OpenOthers: "Laat de rugzak zien van andere spelers." Reload: "Herlaadt de instellingen van de plugin." Update: "Controleert op nieuwe plugin updates." Version: "Geeft details weer over de versie de plugin en diens afhankelijkheden." Backup: "Creëert een back-up van de rugzakken van de spelers." BackupEveryone: "Maakt een back-up van iedereen die momenteel online is." Restore: "Herstelt een back-up." RestoreList: "Laat alle beschikbare back-ups zien." Help: "Laat alle commando's zien met hun beschrijving." Migrate: "Zet de database over naar een ander type." Pickup: "Schakel de status van automatische pickup wanneer de inventaris vol is." Command: Backpack: - backpack - bp - rugzak - rz Open: - open Sort: - sorteer - sort Clean: - clean - schoon Reload: - herlaad - herstart - reload - restart Update: - update Backup: - backup Restore: - restore - herstel ListBackups: - listbackups - lijst - backuplijst Version: - version - versie Help: - help - hulp InventoryClear: - clear - inventoryclear - wis - verwijder Pickup: - pickup # Will be shown in the console during startup LanguageName: "Nederlands" Author: "Le0ne_" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/pl.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cPolecenia nie można używać z konsoli." Ingame: NoPermission: "&cNie masz na to pozwolenia." WorldDisabled: "&cKorzystanie z plecaka jest zabronione na tym świecie." NaN: "[\"\",{\"text\":\"Podana wartość nie jest liczbą\",\"color\":\"red\"}]" OwnBackpackClose: "Plecak zamknięty!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} plecak zamknięty!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Nieprawidłowy plecak." NotAllowedInBackpack: "&c{ItemName}nie jest dozwolone w plecaku." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cNie wolno usuwać skrótu do plecaka z ekwipunku!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cTwój plecak się skurczył! Niektóre przedmioty spadły na ziemię!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} seconds\"}},{\"text\":\"Proszę czekać\",\"color\":\"dark_green\"},{\"text\":\" aż do ponownego otwarcia plecaka.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "W bieżącym trybie gry nie wolno otwierać plecaka." Clean: BackpackCleaned: "Plecak wyczyszczony." BackpackCleanedBy: "Twój plecak został wyczyszczony przez {DisplayName}&r." BackpackCleanedOther: "Plecak gracza {DisplayName}&r został wyczyszczony." Sort: Sorted: "Plecak posortowany." Help: Header: "&6### Paczka poleceń ###" Footer: "&6#############################" Reload: Reloading: "&1Ponowne ładowanie..." Reloaded: "&1Załadowano ponownie!" Update: CheckingForUpdates: "&1Checking for updates ..." Updated: "[\"\",{\"text\":\"Wtyczka zaktualizowana, zostanie załadowana przy następnym restarcie / przeładowaniu\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Brak aktualizacji wtyczki.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Podczas wyszukiwania aktualizacji wystąpił problem! Sprawdź konsolę!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Dostępna jest aktualizacja! Proszę wejść na \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" aby go pobrać!\"}]" Backup: Created: "Utworzono kopię zapasową plecaka." NoBackpack: "Gracz nie ma plecaka lub jego plecak jest pusty." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Kopie zapasowe\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"wyświetlana strona {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Poprzednia <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Wyświetlana strona {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Następna >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "Nie znaleziono kopii zapasowej pasującej{BackupIdentifier} " NoUserToRestoreToFound: "Brak prawidłowego użytkownika do przywrócenia kopii zapasowej do znalezionej." # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Kopia zapasowa została pomyślnie przywrócona." InventoryClear: UnknownPlayer: "&cNie można znaleźć gracza {Name}!" Cleared: "Ekwipunek wyczyszczony." ClearedOther: "Ekwipunek gracza {DisplayName}&r został wyczyszczony." ClearedOtherTarget: "Twój ekwipunek został wyczyszczony przez {DisplayName}&r." Pickup: ToggleOn: "&7Automatyczne zbieranie przedmiotów zostało &aWŁĄCZONE&7." ToggleOff: "&7Automatyczne zbieranie przedmiotów zostało &cWYŁĄCZONE&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Otwiera plecak." Clean: "Czyści plecak." CleanOthers: "Czyści plecak innych graczy." OpenOthers: "Otwiera plecak innych graczy." Reload: "Ponownie ładuje konfigurację wtyczki." Update: "Sprawdza dostępność nowych aktualizacji wtyczek." Version: "Wyświetla szczegóły wersji wtyczki i jej zależności." Backup: "Tworzy kopię zapasową plecaka gracza." BackupEveryone: "Tworzy kopię zapasową wszystkich obecnie online." Restore: "Przywraca kopię zapasową." RestoreList: "Wyświetla wszystkie dostępne kopie zapasowe." Help: "Pokazuje wszystkie dostępne polecenia i ich opis." Migrate: "Migruje używaną bazę danych z jednego typu na inny." Pickup: "Przełącz stan automatycznego zbierania gdy ekwipunek jest pełny." Command: Backpack: - plecak - pk Open: - "otwórz" Sort: - sort - sortuj Clean: - "wyczyść" Reload: - reload - restart Update: - aktualizacja Backup: - backup Restore: - restore ListBackups: - listbackups Version: - wersja Help: - pomoc InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "Polish" Author: "Lisheya" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/pt.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cO comando não pode ser usado no console." Ingame: NoPermission: "&cVocê não tem permissão para isso." WorldDisabled: "&cVocê não pode usar a mochila nesse mundo." NaN: "[\"\",{\"text\":\"Isso não é um número!\",\"color\":\"red\"}]" OwnBackpackClose: "Mochila fechada!" OwnBackpackClose_SendMethod: "action_bar" # Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "Mochila de {OwnerName} fechada!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Mochila inválida." NotAllowedInBackpack: "&c{ItemName} não pode ficar na mochila." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cVocê não deve remover o atalho da mochila do seu inventário!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cSua mochila encolheu! Alguns itens caíram no chão!" Open: # Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Por favor, espere \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} seconds\"}},{\"text\":\" para abrir a mochila novamente.\"}]" # Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Você não pode abrir a mochila nesse modo de jogo." Clean: BackpackCleaned: "Mochila limpa." BackpackCleanedBy: "Sua mochila foi limpa por {DisplayName}&r." BackpackCleanedOther: "A mochila de {DisplayName}&r foi limpa." Sort: Sorted: "Mochila organizada." Help: Header: "&6### Comandos Minepacks ###" Footer: "&6#############################" Reload: Reloading: "&1Recarregando ..." Reloaded: "&1Recarregado!" Update: CheckingForUpdates: "&1Procurando atualizações ..." Updated: "[\"\",{\"text\":\"Plugin atualizado, será carregado no próximo restart/reload.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Plugin atualizado!\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Houve um problema ao procucurar atualizações, olhe o console!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Atualização disponível, vá até \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" para baixa-la!\"}]" Backup: Created: "Backup criado com sucesso." NoBackpack: "O jogador não tem um backup ou a mochila está vazia." Restore: BackupsPerPage: "10" Headline: "[\"\",{\"text\":\"Backups\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"página {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Anterior <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Página {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Próximo >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "Nenhuma correspondência de backup {BackupIdentifier} encontrada" NoUserToRestoreToFound: "Nenhum usuário válido para restaurar o backup encontrado" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Backup carregado com sucesso." InventoryClear: UnknownPlayer: "&cNão foi possível encontrar o jogador {Name}!" Cleared: "Inventário limpo." ClearedOther: "O inventário de {DisplayName}&r foi limpo." ClearedOtherTarget: "Seu inventário foi limpo por {DisplayName}&r." Pickup: ToggleOn: "&7A coleta automática de itens foi &aATIVADA&7." ToggleOff: "&7A coleta automática de itens foi &cDESATIVADA&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Abre sua mochila." Clean: "Limpa sua mochila." CleanOthers: "Limpa a mochila de outros jogadores." OpenOthers: "Abre a mochila de outro jogador." Reload: "Recarrega a configuração do plugin." Update: "Procura por novas atualizações." Version: "Mostra detalhes da versão do plugin e suas dependências." Backup: "Cria um backup da mochila dos jogadores." BackupEveryone: "Cria um backup de todos que estão online no momento." Restore: "Restaura um backup." RestoreList: "Mostra todos os backups disponíveis." Help: "Mostra todos os comandos disponíveis e suas descrições." Migrate: "Migra o banco de dados usado de um tipo para outro." Pickup: "Alterna o estado da coleta automática quando o inventário está cheio." Command: Backpack: - backpack - bp - mochila Open: - open - abrir Sort: - sort - organizar Clean: - clean - clear - empty - limpar Reload: - reload - restart - recarregar Update: - update - atualizar Backup: - backup Restore: - restore - restaurar ListBackups: - listbackups - listarbackups Version: - version - versao Help: - help - ajuda InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "Português" Author: "dotJunyo" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/ru.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cЭту команду нельзя использовать в консоли." Ingame: NoPermission: "&cУ вас недостаточно прав для этого." WorldDisabled: "&cИспользовать рюкзак не разрешено в этом мире." NaN: "[\"\",{\"text\":\"Введенное значение не является числом!\",\"color\":\"red\"}]" OwnBackpackClose: "Рюкзак закрыт!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "Рюкзак {OwnerName} закрыт!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Недействительный рюкзак." NotAllowedInBackpack: "&c{ItemName} нельзя положить в рюкзак." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cВы не можете удалить иконку рюкзака из своего инвентаря!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cВаш рюкзак уменьшился! Некоторые предметы выпали на землю!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Пожалуйста подождите \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} секунд\"}},{\"text\":\", перед тем как снова открыть свой рюкзак.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Вам не разрешено открывать рюкзак в текущем режиме игры." Clean: BackpackCleaned: "Рюкзак очищен." BackpackCleanedBy: "Ваш рюкзак был очищен игроком {DisplayName}&r." BackpackCleanedOther: "{DisplayName}'s&r рюкзак был очищен." Sort: Sorted: "Рюкзак отсортирован." Help: Header: "&6### Команды Minepacks ###" Footer: "&6#############################" Reload: Reloading: "&1Перезагрузка..." Reloaded: "&1Плагин успешно перезагружен!" Update: CheckingForUpdates: "&1Проверка обновлений..." Updated: "[\"\",{\"text\":\"Плагин обновлён и будет загружен после следующей перезагрузки.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Нет доступных обновлений.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"При проверке обновлений произошла ошибка! Пожалуйста проверьте консоль!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Доступно обновление! Пожалуйста, посетите сайт \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" чтобы скачать его!\"}]" Backup: Created: "Рюкзак был успешно скопирован." NoBackpack: "У игрока нет рюкзака, либо он пустой." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Резервные копии\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"страница {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Предыдущая <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Страница {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Следующая >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Пользователь: {BackupPlayerName} ({BackupPlayerUUID})\\\nСоздана: {BackupDate}\"}}]" NoValidBackup: "Резервная копия {BackupIdentifier} не найдена" NoUserToRestoreToFound: "Не найдено действительного пользователя или копии для восстановления" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "dd.MM.yy HH:mm:ss" Restored: "Резервная копия успешно восстановлена." InventoryClear: UnknownPlayer: "&cНе удалось найти игрока {Name}!" Cleared: "Инвентарь очищен." ClearedOther: "{DisplayName}'s&r инвентарь был очищен." ClearedOtherTarget: "Ваш инвентарь был очищен игроком {DisplayName}&r." Pickup: ToggleOn: "&7Автоматический сбор предметов был переключен на &aВКЛ&7." ToggleOff: "&7Автоматический сбор предметов был переключен на &cВЫКЛ&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Открыть ваш рюкзак." Sort: "Отсортировать ваш рюкзак." Clean: "Очистить ваш рюкзак." CleanOthers: "Очистить рюкзак другого игрока." OpenOthers: "Открыть рюкзак другого игрока." Reload: "Перезагрузить конфигурацию плагина." Update: "Проверить плагин на наличие новых версий." Version: "Посмотреть информацию о плагине и о его зависимостях." Backup: "Создать резервную копию рюкзака игрока." BackupEveryone: "Создает резервную копию всех, кто в данный момент находится в сети." Restore: "Восстановить резервную копию." RestoreList: "Посмотреть список всех доступных резервных копий." Help: "Посмотреть все команды и их описание." Migrate: "Изменить тип используемой базы данных." Pickup: "Переключить состояние автоматического подбора, когда инвентарь заполнен." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "russian" Author: "maz1lovo" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/tr.yml ================================================ # To simplify the customisation and the translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cKomut konsoldan kullanılabilir değil." Ingame: NoPermission: "&cBunu yapmak için iznin yok." WorldDisabled: "&cÇantaların kullanımı bu dünyada devredışı." NaN: "[\"\",{\"text\":\"Girilen değer sayı değil!\",\"color\":\"red\"}]" OwnBackpackClose: "Çanta kapandı!" OwnBackpackClose_SendMethod: "action_bar" # Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} adlı kişinin çantası kapandı!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Geçersiz çanta." NotAllowedInBackpack: "&c{ItemName} çanta içinde bulundurulamaz." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cÇanta kısayolunu envanterinizden kaldırmamalısınız!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cÇantanız küçüldü! Bazı eşyalar yere düştü!" Open: # Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Çantanızı geri açana kadar lütfen \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} seconds\"}},{\"text\":\" bekleyin.\"}]" # Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Şu anki oyun modunda çantanızı açamazsınız." Clean: BackpackCleaned: "Çanta temizlendi." BackpackCleanedBy: "Çantanız {DisplayName}&r tarafından temizlendi." BackpackCleanedOther: "{DisplayName}&r çantası temizlendi." Sort: Sorted: "Çanta sıralandı." Help: Header: "&6### Minepacks Komutları ###" Footer: "&6#############################" Reload: Reloading: "&1Tekrar Yükleniyor ..." Reloaded: "&1Tekrar Yüklendi!" Update: CheckingForUpdates: "&1Güncellemeler denetleniyor ..." Updated: "[\"\",{\"text\":\"Eklenti güncellendi, diğer restart/reload işleminde yüklenecek.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Eklenti güncellemesi bulunmuyor.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Güncelleme denetlenirken bir hata oluştu! Lütfen konsolu kontrol edin!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Güncelleme mevcut! Yüklemek için \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" adresini kullanın!\"}]" Backup: Created: "Çanta yedeklendi." NoBackpack: "Oyuncunun bir çantası yok ya da çantası boş." Restore: BackupsPerPage: "10" Headline: "[\"\",{\"text\":\"Yedeklemeler\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"Gösterilen sayfa {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Önceki <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Gösterilen Sayfa {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Sonraki >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "Yedekleme eşleşmesi {BackupIdentifier} bulunamadı" NoUserToRestoreToFound: "Yedekleme için geçerli oyuncu bulunamadı" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Yedek başarıyla geri getirildi." InventoryClear: UnknownPlayer: "&cOyuncu {Name} bulunamadı!" Cleared: "Envanter temizlendi." ClearedOther: "{DisplayName}&r envanteri temizlendi." ClearedOtherTarget: "Envanteriniz {DisplayName}&r tarafından temizlendi." Pickup: ToggleOn: "&7Otomatik eşya toplama &aAÇIK&7 duruma getirildi." ToggleOff: "&7Otomatik eşya toplama &cKAPALI&7 duruma getirildi." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Çantanı açar." Clean: "Çantanı temizler." CleanOthers: "Başka bir oyuncunun çantasını temizler." OpenOthers: "Başkasının çantasını görüntüler." Reload: "Eklentinin config dosyasını tekrar yükler." Update: "Eklenti için yeni güncellemeleri denetler." Version: "Eklenti detaylarını ve gerekliliklerinin çıktısını verir." Backup: "Oyuncunun çantasını yedekler." BackupEveryone: "Şu anda çevrimiçi olan herkesin yedeğini oluşturur." Restore: "Yedeği yükler." RestoreList: "Mevcut tüm yedekleri listeler." Help: "Mevcut tüm komutları ve tanımlarını gösterir." Migrate: "Kullanılan veritabanını bir türden diğerine geçirir." Pickup: "Envanter doluyken otomatik toplama durumunu değiştirir." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "turkish" Author: "imZesha" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/uk.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cКоманда не доступна з консолі." Ingame: NoPermission: "&cВи не маєте прав, щоб зробити це." WorldDisabled: "&cВикористання рюкзака заборонено у цьому світі." NaN: "[\"\",{\"text\":\"Введене значення не є числом!\",\"color\":\"red\"}]" OwnBackpackClose: "Рюкзак зачинен!" OwnBackpackClose_SendMethod: "action_bar" #Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} рюкзак зачинен!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Рюкзак недійсний." NotAllowedInBackpack: "&c{ItemName} не дозволяється носити в рюкзаку." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cВи не можете прибрати рюкзак з інвентарю!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cВаш рюкзак зменшився! Деякі предмети впали на землю!" Open: #Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Будь ласка, почекайте \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} секунд\"}},{\"text\":\", перш ніж знову відкривати рюкзак.\"}]" #Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Ви не маєте права відчиняти рюкзак у поточному режимі гри." Clean: BackpackCleaned: "Рюкзак почищено" BackpackCleanedBy: "Ваш рюкзак був почищен {DisplayName}&r." BackpackCleanedOther: "{DisplayName}&r Рюкзак був почищений." Sort: Sorted: "Рюкзак відсортовано." Help: Header: "&6### Minepacks Команди ###" Footer: "&6#############################" Reload: Reloading: "&aПерезавантаження Minepacks..." Reloaded: "&aMinepacks було перезавантажено!" Update: CheckingForUpdates: "&1Перевірка оновлень..." Updated: "[\"\",{\"text\":\"Плагін було оновлено, він буде завантажен при наступному завантаженні.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Немає оновлень.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Виникла проблема з пошуком оновлень! Будь ласка, перевірте консоль!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Доступно оновлення. Буль ласка, перейдіть по \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" цоб завантажити його!\"}]" Backup: Created: "Рюкзак успішно пройшов резервне копіювання." NoBackpack: "У гравця немає рюкзака або він порожній." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Бекапи\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"сторінка {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Попередня <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Показати сторінку {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Next >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"Користувач: {BackupPlayerName} ({BackupPlayerUUID})\\nСтворено: {BackupDate}\"}}]" NoValidBackup: "Данного бекапа {BackupIdentifier}, не знайдено" NoUserToRestoreToFound: "Не знайдено дійсного користувача для відновлення резервної копії" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Бекап успішно відновлено." InventoryClear: UnknownPlayer: "&cНе вдалося дізнатися про {Name}!" Cleared: "Інвентар відчищено." ClearedOther: "{DisplayName}&r інвентар був відчищен." ClearedOtherTarget: "Речі у вашому рюкзаку були вичищені {DisplayName}&r." Pickup: ToggleOn: "&7Увімкнено автоматичний збір предметів було &aввімкнено&7." ToggleOff: "&7Увімкнено автоматичний збір предметів було &cвимкнено&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "Відчинить рюкзак." Sort: "Відсортує рюкзак." Clean: "Відчистиь рюкзак." CleanOthers: "Відчистить рюкзак іншого гравця." OpenOthers: "Покаже рюкзак іншого гравця." Reload: "Перезавантажить налаштування." Update: "Перевіряє оновленя." Version: "Виводить інформацію про версію плагіна та його залежності." Backup: "Створює резервну копію рюкзака гравця." BackupEveryone: "Створює резервну копію всіх, хто зараз перебуває в мережі." Restore: "Відновлює резервну копію." RestoreList: "Показує всі доступні резервні копії." Help: "Показує всі доступні команди та їх опис." Migrate: "Переносить використовувану базу даних з одного типу в інший." Pickup: "Увімкнути стан автоматичного підбирання, коли інвентар буде заповнено." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "українська" Author: "Andrii(IsPlayer)" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/vi.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&cCommand không sử dụng được từ bảng điều khiển." Ingame: NoPermission: "&cBạn không có quyền làm điều đó." WorldDisabled: "&cViệc sử dụng ba lô không được phép trong thế giới này." NaN: "[\"\",{\"text\":\"Giá trị đã nhập không phải là số!\",\"color\":\"red\"}]" OwnBackpackClose: "Ba lô đóng lại!" OwnBackpackClose_SendMethod: "action_bar" # Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "Ba lô của {OwnerName} đã đóng!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "Ba lô không hợp lệ." NotAllowedInBackpack: "&c{ItemName} không được phép để trong ba lô." NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&cBạn không được xóa phím tắt ba lô khỏi hành trang của mình!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&cBa lô của bạn đã bị thu nhỏ! Một số vật phẩm đã rơi xuống đất!" Open: # Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"Vui lòng đợi \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{ TimeLeft} seconds\"}},{\"text\":\" cho đến khi bạn mở lại ba lô của mình.\"}]" # Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "Bạn không được phép mở ba lô trong chế độ trò chơi hiện tại." Clean: BackpackCleaned: "Đã xóa ba lô." BackpackCleanedBy: "Ba lô của bạn đã bị xóa bởi {DisplayName}&r." BackpackCleanedOther: "Ba lô của {DisplayName} đã bị xóa." Sort: Sorted: "Ba lô được sắp xếp." Help: Header: "&6### Lệnh Minepacks ###" Footer: "&6############################" Reload: Reloading: "&1Đang tải lại Minepack ..." Reloaded: "&1Gói mỏ đã được tải lại!" Update: CheckingForUpdates: "&1Đang kiểm tra các bản cập nhật ..." Updated: "[\"\",{\"text\":\"Plugin đã cập nhật, sẽ được tải vào lần khởi động lại/tải lại tiếp theo.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"Không có bản cập nhật plugin.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"Đã xảy ra sự cố khi tìm kiếm bản cập nhật! Vui lòng kiểm tra bảng điều khiển!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"Có bản cập nhật ! \\\"\",\"color\":\"green\"},{\"text\":\"https://www.spigotmc.org/resources/19286/\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://www.spigotmc.org/resources/19286/\"}},{\"text\":\"\\\" để tải xuống!\"}]" Backup: Created: "Ba lô đã được sao lưu thành công." NoBackpack: "Người chơi không có ba lô hoặc ba lô của anh ta trống rỗng." Restore: BackupsPerPage: 10 Headline: "[\"\",{\"text\":\"Sao lưu\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"hiển thị trang {Trang hiện tại }/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< Trang sau <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" Hiện trang {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> Trang tiếp >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\": {\"action\":\"show_text\",\"value\":\"Người dùng: {BackupPlayerName} ({BackupPlayerUUID})\\nĐã tạo: {BackupDate}\"}}]" NoValidBackup: "Không tìm thấy bản sao lưu phù hợp {BackupIdentifier}" NoUserToRestoreToFound: "Không có người dùng hợp lệ nào để khôi phục bản sao lưu vào tìm thấy" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "Sao lưu đã được khôi phục thành công." InventoryClear: UnknownPlayer: "&cKhông thể tìm thấy người chơi {Name}!" Cleared: "Đã xóa hàng tồn kho." ClearedOther: "Khoảng không quảng cáo của {DisplayName} đã bị xóa." ClearedOtherTarget: "Khoảng không quảng cáo của bạn đã được xóa bởi {DisplayName}&r." Pickup: ToggleOn: "&7Bộ sưu tập vật phẩm tự động đã được bật &bẬT&7." ToggleOff: "&7Tính năng thu thập vật phẩm tự động đã được bật &cTẮT&7." Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}} ,{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "tên người chơi" Description: Backpack: "Mở ba lô của bạn." Sort: "Sắp xếp ba lô của bạn." Clean: "Làm sạch ba lô của bạn." CleanOthers: "Dọn dẹp ba lô của người chơi khác." OpenOthers: "Hiển thị ba lô của người chơi khác." Reload: "Tải lại cấu hình của plugin." Update: "Kiểm tra các bản cập nhật plugin mới." Version: "In chi tiết phiên bản về plugin và phần phụ thuộc của nó." Backup: "Tạo bản sao lưu ba lô của người chơi." BackupEveryone: "Tạo bản sao lưu của mọi người hiện đang trực tuyến." Restore: "Khôi phục một bản sao lưu." RestoreList: "Liệt kê tất cả các bản sao lưu có sẵn." Help: "Hiển thị tất cả các lệnh có sẵn và mô tả của chúng." Migrate: "Di chuyển cơ sở dữ liệu đã sử dụng từ loại này sang loại khác." Pickup: "Chuyển đổi trạng thái lấy hàng tự động khi kho đầy." Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "Vietnamese" Author: "RageOfFire" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/zh_cn.yml ================================================ # To simplify the customisation and translation process please check out the editor: https://ptp.pcgamingfreaks.at Language: NotFromConsole: "&c命令无法从控制台使用。" Ingame: NoPermission: "&c你没有权限这么做。" WorldDisabled: "&c该世界不允许使用背包。" NaN: "[\"\",{\"text\":\"输入的值不是数字!\",\"color\":\"red\"}]" OwnBackpackClose: "背包关闭!" OwnBackpackClose_SendMethod: "action_bar" # Parameter: {OwnerName}, {OwnerDisplayName} PlayerBackpackClose: "{OwnerName} 的背包已关闭!" PlayerBackpackClose_SendMethod: "action_bar" InvalidBackpack: "无效的背包。" NotAllowedInBackpack: "&c{ItemName} 不允许放在背包里。" NotAllowedInBackpack_SendMethod: "action_bar" DontRemoveShortcut: "&c你不能从你的物品栏中删除背包快捷方式!" DontRemoveShortcut_SendMethod: "action_bar" BackpackShrunk: "&c你的背包缩小了!一些物品掉到了地上!" Open: # Parameter: {TimeLeft} time in seconds till the backpack can be reopened, {TimeSpanLeft} time formatted as string till the backpack can be reopened Cooldown: "[{\"text\":\"请等待 \",\"color\":\"dark_green\"},{\"text\":\"{TimeSpanLeft}\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"{TimeLeft} 秒\"}},{\"text\":\" 才能重新打开背包。\"}]" # Parameter: {CurrentGameMode}, {AllowedGameModes} WrongGameMode: "在当前游戏模式下,你不允许打开背包。" Clean: BackpackCleaned: "背包已清空" BackpackCleanedBy: "您的背包 {DisplayName} 已被清空&r。" BackpackCleanedOther: "{DisplayName} &r的背包已经清除。" Sort: Sorted: "整理背包" Help: Header: "&6### Minepacks 指令 ###" Footer: "&6#############################" Reload: Reloading: "&3重载 Minepacks 中……" Reloaded: "&aMinepacks 已重载!" Update: CheckingForUpdates: "&3检查更新中…" Updated: "[\"\",{\"text\":\"插件已更新,将在下次重启时加载.\",\"color\":\"yellow\"}]" NoUpdate: "[\"\",{\"text\":\"没有更新的插件.\",\"color\":\"gold\"}]" UpdateFail: "[\"\",{\"text\":\"在查找更新时出现了问题!请检查控制台!\",\"color\":\"red\"}]" # You can change this message if you like to, but don't cry if the link isn't linking to the plugin anymore! UpdateAvailable: "[{\"text\":\"有一个可用的更新!请浏览 \\\"\",\"color\":\"green\"},{\"text\":\"${project.url}\",\"color\":\"yellow\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"${project.url}\"}},{\"text\":\"\\\" 去下载!\"}]" Backup: Created: "背包备份成功。" NoBackpack: "玩家没有背包或者背包是空的。" Restore: BackupsPerPage: "10" Headline: "[\"\",{\"text\":\"备份\",\"color\":\"yellow\"},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"页面 {CurrentPage}/{MaxPage}\",\"color\":\"gold\"}]" Footer: "[{\"text\":\"<<< 上一页 <<<\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}--\"}},{\"text\":\" 当前页面 {CurrentPage}/{MaxPage} \",\"color\":\"gold\"},{\"text\":\">>> 下一页 >>>\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"/{MainCommand} {SubCommand} {CurrentPage}++\"}}]" BackupEntry: "[\"\",{\"text\":\"{BackupIdentifier}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand} {BackupIdentifier}\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"User: {BackupPlayerName} ({BackupPlayerUUID})\\nCreated: {BackupDate}\"}}]" NoValidBackup: "没有找到匹配 {BackupIdentifier} 的备份" NoUserToRestoreToFound: "没有有效用户可将备份恢复到已找到的位置" # No Json!!! ParameterBackupName: "backup_name" # No Json!!! DateFormat: "yyyy.MM.dd HH:mm:ss" Restored: "备份已成功恢复。" InventoryClear: UnknownPlayer: "&c找不到玩家 {Name}!" Cleared: "背包东西清空。" ClearedOther: "{DisplayName} &r的背包东西已经清空。" ClearedOtherTarget: "已经清空了 {DisplayName} 的背包&r。" Pickup: ToggleOn: "&7自动物品收集已&a开启&7。" ToggleOff: "&7自动物品收集已&c关闭&7。" Commands: HelpFormat: "[\"\",{\"text\":\"/{MainCommand} {SubCommand} {Parameters}\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/{MainCommand} {SubCommand}\"}},{\"text\":\" - \",\"color\":\"white\"},{\"text\":\"{Description}\",\"color\":\"aqua\"}]" PlayerNameVariable: "player_name" Description: Backpack: "打开你的背包。" Sort: "整理你的背包。" Clean: "清空你的背包。" CleanOthers: "清空其他玩家的背包。" OpenOthers: "这是另一个玩家的背包。" Reload: "重新加载插件的配置。" Update: "检查新的插件更新。" Version: "输出关于插件及其依赖项的版本详细信息。" Backup: "创建玩家背包的备份。" BackupEveryone: "创建当前在线的所有人的备份。" Restore: "恢复备份。" RestoreList: "列出所有可用的备份。" Help: "显示所有可用命令及其描述。" Migrate: "将使用的数据库从一种类型迁移到另一种类型。" Pickup: "在物品栏已满时切换自动收集的状态。" Command: Backpack: - backpack - bp Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup # Will be shown in the console during startup LanguageName: "简体中文" Author: "YaoSiQian, Liou_Yang" # Language file version. Don't touch it! Version: 21 ================================================ FILE: Minepacks/resources/lang/zh_tw.yml ================================================ Language: NotFromConsole: "&c指令不能從控制台使用" Ingame: NoPermission: "&c你沒有權限使用" WorldDisabled: "&c這個世界不允許使用背包" NaN: '["",{"text":"輸入的值不是數字!","color":"red"}]' OwnBackpackClose: 背包關閉! OwnBackpackClose_SendMethod: action_bar PlayerBackpackClose: "{OwnerName} 關閉背包!" PlayerBackpackClose_SendMethod: action_bar InvalidBackpack: 無效的背包。 NotAllowedInBackpack: "&c{ItemName} 不允許放在背包裡。" NotAllowedInBackpack_SendMethod: action_bar DontRemoveShortcut: "&c您不得從庫存中刪除背包快捷方式!" DontRemoveShortcut_SendMethod: action_bar BackpackShrunk: "&c你的背包縮小了!一些物品掉到了地上!" Open: Cooldown: '[{"text":"請稍等 ","color":"dark_green"},{"text":"{TimeSpanLeft}","hoverEvent":{"action":"show_text","value":"{TimeLeft} 秒"}},{"text":" 直到你重新打開你的背包。"}]' WrongGameMode: 你不能在當前遊戲模式下打開背包。 Clean: BackpackCleaned: 背包已清空 BackpackCleanedBy: 您的背包已被清空 {DisplayName}&r。 BackpackCleanedOther: "{DisplayName}'s&r 背包已清空。" Sort: Sorted: 整理背包。 Help: Header: "&6### 擴充背包 指令幫助 ###" Footer: "&6#############################" Reload: Reloading: "&3正在重新讀取 Minepacks ..." Reloaded: "&3Minepacks 重新讀取完畢! 翻譯版本 19 Specialbase#0428 & dirtTW" Update: CheckingForUpdates: "&1檢查更新 ..." Updated: '["",{"text":"插件已經更新,重新啟動伺服器後生效/reload。","color":"yellow"}]' NoUpdate: '["",{"text":"沒有更新的版本。","color":"gold"}]' UpdateFail: '["",{"text":"查找更新時出現問題! 請檢查控制台!","color":"red"}]' UpdateAvailable: '[{"text":"有更新可用! 請前往 \"","color":"green"},{"text":"https://www.spigotmc.org/resources/19286/","color":"yellow","underlined":true,"clickEvent":{"action":"open_url","value":"https://www.spigotmc.org/resources/19286/"}},{"text":"\" to download it!"}]' Backup: Created: 背包回復成功。 NoBackpack: 玩家沒有背包或他的背包是空的 Restore: BackupsPerPage: 10 Headline: '["",{"text":"回復","color":"yellow"},{"text":" - ","color":"white"},{"text":"顯示頁面 {CurrentPage}/{MaxPage}","color":"gold"}]' Footer: '[{"text":"<<< 上一頁 <<<","color":"gray","clickEvent":{"action":"run_command","value":"/{MainCommand} {SubCommand} {CurrentPage}--"},"hoverEvent":{"action":"show_text","value":"/{MainCommand} {SubCommand} {CurrentPage}--"}},{"text":" Showing page {CurrentPage}/{MaxPage} ","color":"gold"},{"text":">>> 下一頁 >>>","color":"gray","clickEvent":{"action":"run_command","value":"/{MainCommand} {SubCommand} {CurrentPage}++"},"hoverEvent":{"action":"show_text","value":"/{MainCommand} {SubCommand} {CurrentPage}++"}}]' BackupEntry: '["",{"text":"{BackupIdentifier}","clickEvent":{"action":"suggest_command","value":"/{MainCommand} {SubCommand} {BackupIdentifier}"},"hoverEvent":{"action":"show_text","value":"User: {BackupPlayerName} ({BackupPlayerUUID})\nCreated: {BackupDate}"}}]' NoValidBackup: "無法尋找備份 {BackupIdentifier} " NoUserToRestoreToFound: 找不到可將備份還原到的有效用戶 ParameterBackupName: backup_name DateFormat: yyyy.MM.dd HH:mm:ss Restored: 還原備份成功 InventoryClear: UnknownPlayer: "&c找不到玩家 {Name}!" Cleared: 清空背包。 ClearedOther: "{DisplayName}&r 已清空背包。" ClearedOtherTarget: "你的背包已遭清空 {DisplayName}&r。" Pickup: ToggleOn: "&7自動物品收集已切換為 &a開&7。" ToggleOff: "&7自動物品收集已切換為 &c關&7。" Commands: HelpFormat: '["",{"text":"/{MainCommand} {SubCommand} {Parameters}","clickEvent":{"action":"suggest_command","value":"/{MainCommand} {SubCommand}"}},{"text":" - ","color":"white"},{"text":"{Description}","color":"aqua"}]' PlayerNameVariable: player_name Description: Backpack: 開啟你的背包 Sort: 整理你的背包 Clean: 清空你的背包 CleanOthers: 清理其他玩家的背包 OpenOthers: 看茶另一個玩家的背包 Reload: 重新整理這個插件 Update: 檢查更新 Version: 列出有關插件及其依賴項的版本詳細信息 Backup: 新增玩家背包的備份。 BackupEveryone: 建立目前在線所有人的備份。 Restore: 恢復備份。 RestoreList: 列出所有玩家的備份。 Help: 顯示此指令表。 Migrate: 將使用的數據庫從一種類型遷移到另一種類型。 Pickup: 切換背包庫存滿時的自動拾取狀態。 Command: Backpack: - backpack - bp - bag Open: - open Sort: - sort Clean: - clean - clear - empty Reload: - reload - restart Update: - update Backup: - backup Restore: - restore ListBackups: - listbackups Version: - version Help: - help InventoryClear: - clear - inventoryclear - clean Pickup: - pickup LanguageName: 繁體中文 Author: Specialbase#0428 & dirtTW Version: 21 ================================================ FILE: Minepacks/resources/plugin.yml ================================================ name: "${project.name}" author: "${author}" website: "${project.url}" main: "${mainClass}" description: "${project.description}" version: "${pluginVersion}" api-version: "1.13" depend: [${dependencies}] softdepend: [MVdWPlaceholderAPI, PlaceholderAPI ${soft-dependencies}] folia-supported: true permissions: backpack.*: description: Gives access to the full Minepacks functionality. children: backpack.use: true backpack.size.6: true backpack.keepOnDeath: true backpack.clean: true backpack.fullpickup: true backpack.fullpickup.toggle: true backpack.bypass: true backpack.admin: true backpack.disable: description: This permission group can be used to disable the plugin for certian users/groups/worlds. default: false children: backpack.use: false backpack.others: false backpack.keepOnDeath: true backpack.clean: false backpack.user: description: This permission can be used to give a user the basic backpack size and allow him to use the backpack. children: backpack.use: true backpack.size.1: true backpack.clean: true backpack.sort: true backpack.userBig: description: This permission can be used to give a user the biggest backpack size and allow him to use the backpack. children: backpack.use: true backpack.size.6: true backpack.clean: true backpack.sort: true backpack.bypass: children: backpack.ignoreGameMode: true backpack.ignoreWorldBlacklist: true backpack.noCooldown: true backpack.admin: children: backpack.others: true backpack.others.edit: true backpack.clean.others: true backpack.update: true backpack.reload: true backpack.migrate: true backpack.use: description: Allows a player to open the backpack. default: false backpack.size.1: description: Mini size for a backpack, if the player has backpack permission he will also have at least a backpack with the size 1. default: false backpack.size.2: description: 2*9 backpack default: false backpack.size.3: description: 3*9 backpack default: false backpack.size.4: description: 4*9 backpack default: false backpack.size.5: description: 5*9 backpack default: false backpack.size.6: description: 6*9 backpack default: false backpack.sort: description: Allows the player to sort their own backpack. default: false backpack.clean: description: Allows the player to clean their own backpack. default: false backpack.fullpickup: description: Allows the player to automatically pick up items when their inventory is full (function needs to be enabled in the config) default: true backpack.fullpickup.toggle: description: Allows the player to toggle the automatic pickup feature. default: true backpack.clean.other: description: Allows the player to clean other players backpacks. default: op children: backpack.clean: true backpack.others: description: Allows the player open backpacks of other players. default: op backpack.others.edit: description: Allows the player to edit backpacks of other players. default: op children: backpack.others: true backpack.keepOnDeath: description: Allows the player to keep their items in their backpack on death. default: op backpack.noCooldown: description: Allows to bypass the cooldown to open the backpack. default: op backpack.ignoreGameMode: description: Allows to bypass the game-mode restriction. default: op backpack.ignoreWorldBlacklist: description: Allows to bypass the world blacklist. default: op backpack.update: description: Allows to update the plugin. default: op backpack.reload: description: Allows to reload the config. default: op backpack.migrate: description: Allows migrating data from one format to another. default: op backpack.backup: description: Allows to create a backup of a backpack. default: op backpack.restore: description: Allows to restore a backup of a backpack. default: op backpack.version: description: Allows to print the version details of the plugin and it's dependencies. default: op clearInventory: description: Allows the player to clear their own inventory. default: op clearInventory.other: description: Allows the player to clear the inventory of other players. default: op children: clearInventory: true ================================================ FILE: Minepacks/resources/update.yml ================================================ UpdateProviders: Bukkit: Type: Bukkit ProjectId: 83445 Spigot: Type: Spigot ProjectId: 19286 Filename: "minepacks.jar" GitHub: Type: GitHub Owner: GeorgH93 Repo: Minepacks GitHubStandalone: Type: GitHub Owner: GeorgH93 Repo: Minepacks JarSearch: ".*-Standalone\\.jar" GitHubRelease: Type: GitHub Owner: GeorgH93 Repo: Minepacks JarSearch: ".*-Release\\.jar" JenkinsMaster: Type: Jenkins Server: "https://ci.pcgamingfreaks.at" Job: "Minepacks" JenkinsMasterStandalone: Type: Jenkins Server: "https://ci.pcgamingfreaks.at" Job: "Minepacks" Filter: ".*-Standalone.jar" JenkinsMasterRelease: Type: Jenkins Server: "https://ci.pcgamingfreaks.at" Job: "Minepacks" Filter: ".*-Release.jar" JenkinsDev: Type: Jenkins Server: "https://ci.pcgamingfreaks.at" Job: "Minepacks Dev" UpdateChannels: Release: Release: [ Bukkit, Spigot, GitHubRelease ] Standalone: [ GitHubStandalone ] Normal: [ GitHub ] Master: Release: [ JenkinsMasterRelease ] Standalone: [ JenkinsMasterStandalone ] Normal: [ JenkinsMaster ] Dev: Normal: [ JenkinsDev ] DefaultChannel: "${updateChannel}" ReleaseType: "${releaseType}" ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Backpack.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.InventoryUtils; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper.InventoryCompressor; import at.pcgamingfreaks.Util.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class Backpack implements at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack { @Setter(AccessLevel.PACKAGE) private static ShrinkApproach shrinkApproach = ShrinkApproach.COMPRESS; @Setter(AccessLevel.PACKAGE) private static Message messageBackpackShrunk = new Message("Backpack shrunk!"); private static Object titleOwnGlobal; private static String titleFormat, titleOtherFormat; private static boolean useDynTitle; private final Object titleOwn; private final String titleOther; @Getter private final UUID ownerId; private final Map opened = new ConcurrentHashMap<>(); //Thanks Minecraft 1.14 private Inventory bp; @Getter private int size; @Getter @Setter private int ownerDatabaseId; private boolean hasChanged; public static void setTitle(final @NotNull String title, final @NotNull String titleOther) { titleOwnGlobal = title.contains("%s") ? null : InventoryUtils.prepareTitleForOpenInventoryWithCustomTitle(title); titleFormat = title; titleOtherFormat = titleOther; useDynTitle = !title.equals(titleOther); } public Backpack(OfflinePlayer owner) { this(owner, 9); } public Backpack(OfflinePlayer owner, int size) { this(owner, size, -1); } public Backpack(OfflinePlayer owner, int size, int ID) { if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_14) && size > 54) { size = 54; Minepacks.getInstance().getLogger().warning("Backpacks with more than 6 rows are no longer supported on Minecraft 1.14 and up!"); } this.ownerId = owner.getUniqueId(); titleOther = StringUtils.limitLength(String.format(titleOtherFormat, owner.getName()), 32); bp = Bukkit.createInventory(this, size, titleOther); this.size = size; ownerDatabaseId = ID; if (titleOwnGlobal != null) titleOwn = titleOwnGlobal; else titleOwn = InventoryUtils.prepareTitleForOpenInventoryWithCustomTitle(String.format(titleFormat, owner.getName())); } public Backpack(final OfflinePlayer owner, ItemStack[] backpack, final int ID) { this(owner, backpack.length, ID); if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_14) && backpack.length > 54) { // Try to optimize space usage to compress items into only 6 rows InventoryCompressor compressor = new InventoryCompressor(backpack, 54); final List toMuch = compressor.compress(); backpack = compressor.getTargetStacks(); if(!toMuch.isEmpty()) { Minepacks.getInstance().getLogger().warning(owner.getName() + "'s backpack has to many items."); if(owner.isOnline()) { Minepacks.getScheduler().runNextTick(task -> { if(owner.isOnline()) { Player player = owner.getPlayer(); assert player != null; Minepacks.getScheduler().runAtEntity(player, task1 -> { Map left = player.getInventory().addItem(toMuch.toArray(new ItemStack[0])); left.forEach((id, stack) -> player.getWorld().dropItemNaturally(player.getLocation(), stack)); this.setChanged(); }); } }); } else throw new RuntimeException("Backpack to big for MC 1.14 and up!"); } } bp.setContents(backpack); } @Override @Deprecated public @NotNull OfflinePlayer getOwner() { return Bukkit.getServer().getOfflinePlayer(ownerId); } @Override public @Nullable Player getOwnerPlayer() { return Bukkit.getServer().getPlayer(ownerId); } public void checkResize() { Player owner = Bukkit.getServer().getPlayer(this.ownerId); if(owner != null) { if(owner.hasPermission(Permissions.USE)) { int size = Minepacks.getInstance().getBackpackPermSize(owner); if(size != bp.getSize()) { boolean dropped = false; List items = setSize(size); for(ItemStack i : items) { if(i != null) { owner.getWorld().dropItemNaturally(owner.getLocation(), i); dropped = true; } } if (dropped) { messageBackpackShrunk.send(owner); } } } } } @Override public void open(final @NotNull Player player, final boolean editable) { checkResize(); opened.put(player, editable); if(useDynTitle && ownerId.equals(player.getUniqueId())) InventoryUtils.openInventoryWithCustomTitlePrepared(player, bp, titleOwn); else player.openInventory(bp); } @Override public void open(final @NotNull Player player, final boolean editable, final @Nullable String title) { if(title == null) { open(player, editable); return; } checkResize(); opened.put(player, editable); InventoryUtils.openInventoryWithCustomTitle(player, bp, title); } public void close(Player p) { opened.remove(p); } public void closeAll() { opened.forEach((key, value) -> key.closeInventory()); opened.clear(); save(); } @Override public boolean isOpen() { return !opened.isEmpty(); } @Override public boolean canEdit(@NotNull Player player) { return opened.containsKey(player) && opened.get(player); } public @NotNull List setSize(int newSize) { opened.forEach((key, value) -> key.closeInventory()); // Close all open views of the inventory List removedItems; ItemStack[] itemStackArray; if(bp.getSize() > newSize) { InventoryCompressor compressor = new InventoryCompressor(bp.getContents(), newSize); switch(shrinkApproach) { case FAST: compressor.fast(); break; case COMPRESS: compressor.compress(); break; case SORT: compressor.sort(); break; } itemStackArray = compressor.getTargetStacks(); removedItems = compressor.getToMuch(); } else { itemStackArray = bp.getContents(); removedItems = new ArrayList<>(0); } bp = Bukkit.createInventory(bp.getHolder(), newSize, titleOther); for(int i = 0; i < itemStackArray.length; i++) { bp.setItem(i, itemStackArray[i]); } setChanged(); save(); // Make sure the new inventory is saved size = newSize; opened.forEach((key, value) -> key.openInventory(bp)); return removedItems; } @Override public @NotNull Inventory getInventory() { return bp; } @Override public boolean hasChanged() { return hasChanged; } @Override public void setChanged() { hasChanged = true; } @Override public void save() { if(hasChanged()) { Minepacks.getInstance().getDatabase().saveBackpack(this); hasChanged = false; } } public void forceSave() { hasChanged = true; save(); } public void backup() { Minepacks.getInstance().getDatabase().backup(this); } @Override public void clear() { bp.clear(); setChanged(); save(); } @Override public void drop(final @NotNull Location location) { InventoryUtils.dropInventory(bp, location); setChanged(); save(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/CancellableRunnable.java ================================================ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgf.libs.com.tcoded.folialib.impl.PlatformScheduler; import at.pcgf.libs.com.tcoded.folialib.wrapper.task.WrappedTask; public abstract class CancellableRunnable { protected WrappedTask task = null; public abstract void run(); public abstract void schedule(); public void cancel() { if (task != null) { task.cancel(); } } protected PlatformScheduler getScheduler() { return Minepacks.getScheduler(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/BackupCommand.java ================================================ /* * Copyright (C) 2021 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; public class BackupCommand extends MinepacksCommand { private final Message messageCreated, messageNoBackpack; private final String helpParam, helpParamEveryone, descriptionEveryone; public BackupCommand(Minepacks plugin) { super(plugin, "backup", plugin.getLanguage().getTranslated("Commands.Description.Backup"), Permissions.BACKUP, plugin.getLanguage().getCommandAliases("Backup")); helpParam = "<" + plugin.getLanguage().get("Commands.PlayerNameVariable") + ">"; helpParamEveryone = "!everyone!"; descriptionEveryone = plugin.getLanguage().getTranslated("Commands.Description.BackupEveryone"); messageCreated = plugin.getLanguage().getMessage("Ingame.Backup.Created"); messageNoBackpack = plugin.getLanguage().getMessage("Ingame.Backup.NoBackpack"); } @Override public void execute(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { if(args.length == 1) { if(args[0].equalsIgnoreCase("!everyone!")) { for(Player player : plugin.getServer().getOnlinePlayers()) { backup(sender, player); } } else { //noinspection deprecation backup(sender, plugin.getServer().getOfflinePlayer(args[0])); } } else { showHelp(sender, mainCommandAlias); } } private void backup(final @NotNull CommandSender sender, final @NotNull OfflinePlayer offlinePlayer) { getMinepacksPlugin().getBackpack(offlinePlayer, new Callback() { @Override public void onResult(Backpack backpack) { ((at.pcgamingfreaks.Minepacks.Bukkit.Backpack) backpack).backup(); messageCreated.send(sender); } @Override public void onFail() { messageNoBackpack.send(sender); } }, false); } @Override public List tabComplete(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { return Utils.getPlayerNamesStartingWith(args[args.length - 1], sender); } @Override public List getHelp(final @NotNull CommandSender requester) { List help = new ArrayList<>(1); help.add(new HelpData(getTranslatedName(), helpParam, getDescription())); help.add(new HelpData(getTranslatedName(), helpParamEveryone, descriptionEveryone)); return help; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/ClearCommand.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholders; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.List; public class ClearCommand extends MinepacksCommand { private final Message messageCleared, messageClearedOther, messageClearedBy; private final String helpParam, descriptionCleanOthers; public ClearCommand(Minepacks plugin) { super(plugin, "clear", plugin.getLanguage().getTranslated("Commands.Description.Clean"), Permissions.CLEAN, plugin.getLanguage().getCommandAliases("Clean")); descriptionCleanOthers = plugin.getLanguage().getTranslated("Commands.Description.CleanOthers"); helpParam = "<" + plugin.getLanguage().get("Commands.PlayerNameVariable") + ">"; messageCleared = plugin.getLanguage().getMessage("Ingame.Clean.BackpackCleaned"); messageClearedBy = plugin.getLanguage().getMessage("Ingame.Clean.BackpackCleanedBy").placeholders(Placeholders.PLAYER_NAME); messageClearedOther = plugin.getLanguage().getMessage("Ingame.Clean.BackpackCleanedOther").placeholders(Placeholders.PLAYER_NAME); } @Override public void execute(final @NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { OfflinePlayer target = null; if(commandSender instanceof Player && args.length < 2) { Player player = (Player) commandSender; target = (args.length == 1 && player.hasPermission(Permissions.CLEAN_OTHER)) ? Bukkit.getOfflinePlayer(args[0]) : player; } else if(args.length == 1) target = Bukkit.getOfflinePlayer(args[0]); if(target != null) { getMinepacksPlugin().getBackpack(target, new Callback() { @Override public void onResult(Backpack backpack) { if(backpack != null) { backpack.clear(); if(commandSender instanceof Player && ((Player) commandSender).getUniqueId().equals(backpack.getOwnerId())) { messageCleared.send(commandSender); } else { Player owner = backpack.getOwnerPlayer(); if(owner != null) { messageClearedOther.send(commandSender, owner); messageClearedBy.send(owner, commandSender); } else { messageClearedOther.send(commandSender, backpack.getOwner()); } } } else { ((Minepacks) getMinepacksPlugin()).messageInvalidBackpack.send(commandSender); } } @Override public void onFail() { ((Minepacks) getMinepacksPlugin()).messageInvalidBackpack.send(commandSender); } }); } else { showHelp(commandSender, mainCommandAlias); } } @Override public List tabComplete(@NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { if(args.length > 0 && (!(commandSender instanceof Player) || commandSender.hasPermission(Permissions.CLEAN_OTHER))) { return Utils.getPlayerNamesStartingWith(args[args.length - 1], commandSender); } return null; } @Override public List getHelp(@NotNull CommandSender requester) { List help = super.getHelp(requester); if(!(requester instanceof Player) || requester.hasPermission(Permissions.CLEAN_OTHER)) { //noinspection ConstantConditions help.add(new HelpData(getTranslatedName(), helpParam, descriptionCleanOthers)); } return help; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/CommandManager.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Command.CommandExecutorWithSubCommandsGeneric; import at.pcgamingfreaks.Bukkit.Command.RegisterablePluginCommand; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.ConsoleColor; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommandManager; import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Reflection; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.logging.Level; public class CommandManager extends CommandExecutorWithSubCommandsGeneric /*if_not[STANDALONE]*/ implements MinepacksCommandManager /*end[STANDALONE]*/ { private final Minepacks plugin; private final RegisterablePluginCommand backpackCommand; private final Message helpFormat; public CommandManager(@NotNull Minepacks plugin) { this.plugin = plugin; // Registering the backpack command with the translated aliases backpackCommand = new RegisterablePluginCommand(plugin, "backpack", plugin.getLanguage().getCommandAliases("Backpack")); backpackCommand.registerCommand(); backpackCommand.setExecutor(this); backpackCommand.setTabCompleter(this); //TODO handle click action placeholder helpFormat = plugin.getLanguage().getMessage("Commands.HelpFormat").placeholder("MainCommand").placeholder("SubCommand").placeholder("Parameters").placeholder("Description");//.placeholder("suggest_command", "%5\\$s"); // Setting the help format for the marry commands as well as the no permissions and not from console message try { // Show help function Reflection.setStaticField(MinepacksCommand.class, "minepacksPlugin", plugin); // Plugin instance Reflection.setStaticField(MinepacksCommand.class, "minepacksCommandManager", this); // Command manager instance Reflection.setStaticField(MinepacksCommand.class, "showHelp", this.getClass().getDeclaredMethod("sendHelp", CommandSender.class, String.class, Collection.class)); Reflection.setStaticField(MinepacksCommand.class, "messageNoPermission", plugin.messageNoPermission); // No permission message Reflection.setStaticField(MinepacksCommand.class, "messageNotFromConsole", plugin.messageNotFromConsole); // Not from console message } catch(Exception e) { plugin.getLogger().log(Level.SEVERE, e, () -> ConsoleColor.RED + "Unable to set the help format. Default format will be used.\nMore details:" + ConsoleColor.RESET); } // Init backpack commands defaultSubCommand = new OpenCommand(plugin); registerSubCommand(defaultSubCommand); if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_8)) registerSubCommand(new SortCommand(plugin)); registerSubCommand(new ClearCommand(plugin)); registerSubCommand(new ReloadCommand(plugin)); registerSubCommand(new UpdateCommand(plugin)); registerSubCommand(new BackupCommand(plugin)); registerSubCommand(new RestoreCommand(plugin)); registerSubCommand(new MigrateCommand(plugin)); registerSubCommand(new VersionCommand(plugin)); if (plugin.getConfiguration().isFullInvToggleAllowed()) registerSubCommand(new PickupCommand(plugin)); registerSubCommand(new DebugCommand(plugin)); registerSubCommand(new HelpCommand(plugin, commands, this)); } @Override public void close() { backpackCommand.unregisterCommand(); super.close(); } @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { if(sender instanceof Player) { WorldBlacklistMode disabled = plugin.isDisabled((Player) sender); if(disabled != WorldBlacklistMode.None) { switch(disabled) { case Message: plugin.messageWorldDisabled.send(sender); break; case MissingPermission: plugin.messageNoPermission.send(sender); break; case NoPlugin: return false; } return true; } } else if(args.length == 0) // If the command was executed in the console without parameters { args = new String[]{"help"}; // Show help } return super.onCommand(sender, command, alias, args); } @Override public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { if(sender instanceof Player) { WorldBlacklistMode disabled = plugin.isDisabled((Player) sender); if(disabled != WorldBlacklistMode.None) { if (disabled == WorldBlacklistMode.Message) plugin.messageWorldDisabled.send(sender); else if (disabled == WorldBlacklistMode.MissingPermission) plugin.messageNoPermission.send(sender); return null; } } return super.onTabComplete(sender, command, alias, args); } public void sendHelp(CommandSender target, String mainCommandAlias, Collection data) { for(HelpData d : data) { helpFormat.send(target, mainCommandAlias, d.getTranslatedSubCommand(), d.getParameter(), d.getDescription(), d.getClickAction().name().toLowerCase(Locale.ROOT)); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/DebugCommand.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Message.MessageBuilder; import at.pcgamingfreaks.Bukkit.Util.InventoryUtils; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Message.MessageClickEvent; import at.pcgamingfreaks.Message.MessageColor; import at.pcgamingfreaks.Message.MessageFormat; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.apache.commons.lang.exception.ExceptionUtils; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import lombok.SneakyThrows; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; public class DebugCommand extends MinepacksCommand { private final Message messageDone, messageStart; private BufferedWriter writer = null; public DebugCommand(final @NotNull Minepacks plugin) { super(plugin, "debug", "Just for debug reasons", Permissions.RELOAD, true); MessageBuilder builder = new MessageBuilder("Please do not interact with your game for the next minute!", MessageColor.GOLD); builder.appendNewLine().append("The plugin will now collect data about your server and plugins.").appendNewLine(); builder.append("This will involve opening inventory's and your backpack.").appendNewLine(); builder.append("Please do not interact with your game till this is over!", MessageColor.RED, MessageFormat.BOLD); messageStart = builder.getMessage(); builder = new MessageBuilder("All data has been collected!", MessageColor.GREEN, MessageFormat.BOLD).appendNewLine(); builder.append("You can now interact with your game again.").appendNewLine(); builder.append("The collected data can be found in your plugins directory inside the 'debug.txt' file.").appendNewLine(); builder.append("Please upload this file to "); builder.append("https://pastebin.com/", MessageColor.YELLOW, MessageFormat.UNDERLINE).onClick(MessageClickEvent.ClickEventAction.OPEN_URL, "https://pastebin.com/"); builder.append(" and send the link to the developer."); messageDone = builder.getMessage(); } @SneakyThrows private void debugSystem(final @NotNull CommandSender commandSender) { final Player sender = (Player) commandSender; messageStart.send(sender); File debugFile = new File(plugin.getDataFolder(), "debug.txt"); if(debugFile.exists() && !debugFile.delete()) { plugin.getLogger().warning("Unable to delete debug.txt file!"); } writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(debugFile.toPath()), StandardCharsets.UTF_8)); writer.append(plugin.getDescription().getName()).append(" Version: ").append(plugin.getDescription().getVersion()); writer.append("\nServer: ").append(Bukkit.getServer().getBukkitVersion()).append(" (").append(Bukkit.getServer().getVersion()).append(")"); writer.append("\nJava: ").append(System.getProperty("java.version")); writer.append("\nProxy: ").append(Utils.detectBungeeCord() ? "Bungee" : (Utils.detectVelocity() ? "Velocity" : "None")); writer.append("\nOnline Mode: ").append(String.valueOf(Bukkit.getServer().getOnlineMode())).append(" ; Proxy Online Mode: ").append(String.valueOf(Utils.getBungeeOrVelocityOnlineMode())); writer.append("\n\nPlugins:\n"); for(Plugin p : Bukkit.getServer().getPluginManager().getPlugins()) { writer.append(p.getName()).append(' ').append(p.getDescription().getVersion()).append('\n'); } writer.append("\nPlugin Config:\n"); try(BufferedReader configReader = new BufferedReader(new InputStreamReader(Files.newInputStream(new File(plugin.getDataFolder(), "config.yml").toPath()), StandardCharsets.UTF_8))) { String line; while((line = configReader.readLine()) != null) { if(line.isEmpty()) continue; if(line.contains("Host") || line.contains("Password") || line.contains("User")) line = line.replaceAll("^(\\s+\\w+):.*$", "$1: ********"); writer.append(line).append('\n'); } } writer.append("\n\n\nSelf-test results:\n"); ItemStack slot = sender.getInventory().getItem(0); if(slot == null || slot.getAmount() == 0 || slot.getType() == Material.AIR) sender.getInventory().setItem(0, new ItemStack(Material.ACACIA_BOAT)); Minepacks.getScheduler().runAtEntityLater(sender, () -> sender.performCommand("backpack"), 5*20L); Minepacks.getScheduler().runAtEntityLater(sender, () -> Bukkit.getPluginManager().callEvent(new ClickEvent(sender.getOpenInventory(), InventoryType.SlotType.QUICKBAR, InventoryUtils.getPlayerTopInventory(sender).getSize() + 27, ClickType.LEFT, InventoryAction.PICKUP_ALL)), 10*20L); Minepacks.getScheduler().runAtEntityLater(sender, sender::closeInventory, 20*20L); Minepacks.getScheduler().runLater(() -> { try { writer.flush(); writer.close(); writer = null; } catch(Exception e) { plugin.getLogger().log(Level.SEVERE, "Error while writing debug file.", e);} sender.getInventory().setItem(0, slot); messageDone.send(sender); }, 30*20L); } @SneakyThrows @Override public void execute(@NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { if(writer != null) return; if (args.length == 2 && args[0].equals("permissions")) { Player player = Bukkit.getServer().getPlayer(args[1]); if (player == null) { commandSender.sendMessage("Player " + args[1] + " is offline."); return; } commandSender.sendMessage("### Permissions for " + player.getName() + " ###"); for(String perm : Permissions.getPermissions()) { commandSender.sendMessage(perm + ": " + player.hasPermission(perm)); } commandSender.sendMessage("###############################"); } else if (args.length == 2 && args[0].equals("size")) { executeSize(commandSender, args[1]); } else { debugSystem(commandSender); } } void executeSize(final @NotNull CommandSender commandSender, final @NotNull String playerName) { Player player = Bukkit.getServer().getPlayer(playerName); if (player == null) { commandSender.sendMessage("Player " + playerName + " is offline."); return; } Backpack bp = Minepacks.getInstance().getBackpackCachedOnly(player); int bpSize = -1, bpInvSize = -1, sizeShouldBe = Minepacks.getInstance().getBackpackPermSize(player); String actualSize = "backpack not loaded", actualSizeInventory = "backpack not loaded"; if (bp != null) { bpSize = bp.getSize(); bpInvSize = bp.getInventory().getSize(); actualSize = String.valueOf(bpSize); actualSizeInventory = String.valueOf(bpInvSize); } commandSender.sendMessage("### Backpack size for " + player.getName() + " ###"); commandSender.sendMessage("Size: " + actualSize); commandSender.sendMessage("Inventory Size: " + actualSizeInventory); commandSender.sendMessage("Should be: " + sizeShouldBe); if (bpSize != sizeShouldBe && bp != null) { commandSender.sendMessage("Size mismatch detected, attempt resize ..."); ((at.pcgamingfreaks.Minepacks.Bukkit.Backpack) bp).checkResize(); if (bp.getSize() != sizeShouldBe) { commandSender.sendMessage("Failed to resize backpack."); } else { commandSender.sendMessage("Resized backpack successfully."); } } if (bp != null && bp.getSize() != bp.getInventory().getSize()) { commandSender.sendMessage("Inventory size does not match backpack size!"); } commandSender.sendMessage("Player class: " + player.getClass().getName()); commandSender.sendMessage("###############################"); } @Override public List tabComplete(@NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { if (args.length == 1) { List completeList = new ArrayList<>(3); if ("size".startsWith(args[0])) { completeList.add("size"); } if ("system".startsWith(args[0])) { completeList.add("system"); } if ("permissions".startsWith(args[0])) { completeList.add("permissions"); } return completeList; } else if (args.length == 2) { return Utils.getPlayerNamesStartingWith(args[args.length - 1], null); } return null; } @Override public @Nullable List getHelp(@NotNull CommandSender requester) { return null; } private class ClickEvent extends InventoryClickEvent { public ClickEvent(@NotNull InventoryView view, InventoryType.@NotNull SlotType type, int slot, @NotNull ClickType click, @NotNull InventoryAction action) { super(view, type, slot, click, action); } @SneakyThrows @Override public void setCancelled(boolean toCancel) { super.setCancelled(toCancel); writer.append(ExceptionUtils.getStackTrace(new Exception("Click event has been canceled!!!"))); writer.append("\n\n"); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/HelpCommand.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class HelpCommand extends MinepacksCommand { private final Collection commands; private final Message messageHeader, messageFooter; private final CommandManager commandManager; public HelpCommand(Minepacks plugin, Collection commands, CommandManager commandManager) { super(plugin, "help", plugin.getLanguage().getTranslated("Commands.Description.Help"), plugin.getLanguage().getCommandAliases("Help")); this.commands = commands; this.commandManager = commandManager; messageHeader = plugin.getLanguage().getMessage("Ingame.Help.Header"); messageFooter = plugin.getLanguage().getMessage("Ingame.Help.Footer"); } @Override public void execute(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { messageHeader.send(sender); Collection help = new ArrayList<>(), temp; for(MinepacksCommand cmd : commands) { temp = cmd.doGetHelp(sender); if(temp != null) help.addAll(temp); } commandManager.sendHelp(sender, mainCommandAlias, help); messageFooter.send(sender); //TODO: pages } @Override public List tabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/InventoryClearCommand.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Command.RegisterablePluginCommand; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Minepacks.Bukkit.API.Events.InventoryClearEvent; import at.pcgamingfreaks.Minepacks.Bukkit.API.Events.InventoryClearedEvent; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholders; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; public class InventoryClearCommand implements CommandExecutor, TabCompleter { private final Minepacks plugin; private final RegisterablePluginCommand command; private final Message messageUnknownPlayer, messageOwnInventoryCleared, messageOtherInventoryCleared, messageInventoryWasCleared; public InventoryClearCommand(final @NotNull Minepacks plugin) { this.plugin = plugin; command = new RegisterablePluginCommand(plugin, "clearinventory", plugin.getLanguage().getCommandAliases("InventoryClear")); command.registerCommand(); command.setExecutor(this); command.setTabCompleter(this); // Load messages messageUnknownPlayer = plugin.getLanguage().getMessage("Ingame.InventoryClear.UnknownPlayer").placeholder("Name"); messageOwnInventoryCleared = plugin.getLanguage().getMessage("Ingame.InventoryClear.Cleared"); messageOtherInventoryCleared = plugin.getLanguage().getMessage("Ingame.InventoryClear.ClearedOther").placeholders(Placeholders.PLAYER_NAME); messageInventoryWasCleared = plugin.getLanguage().getMessage("Ingame.InventoryClear.ClearedOtherTarget").placeholders(Placeholders.PLAYER_NAME); } public void close() { command.unregisterCommand(); } private void clearInventory(Player player, CommandSender sender) { InventoryClearEvent clearEvent = new InventoryClearEvent(player, sender); Bukkit.getPluginManager().callEvent(clearEvent); if(clearEvent.isCancelled()) return; player.getInventory().clear(); if(sender.equals(player)) { messageOwnInventoryCleared.send(player); } else { messageInventoryWasCleared.send(player, sender); messageOtherInventoryCleared.send(sender, player); } Bukkit.getPluginManager().callEvent(new InventoryClearedEvent(player, sender)); } @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if(sender.hasPermission(Permissions.INVENTORY_CLEAR)) { if(args.length > 0) { if(sender.hasPermission(Permissions.INVENTORY_CLEAR_OTHER)) { for(String name : args) { Player player = plugin.getServer().getPlayer(name); if(player == null) { messageUnknownPlayer.send(sender, name); } else { clearInventory(player, sender); } } } else { plugin.messageNoPermission.send(sender); } } else if(sender instanceof Player) { clearInventory((Player) sender, sender); } else { sender.sendMessage("/clear "); //TODO } } else { plugin.messageNoPermission.send(sender); } return true; } @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { if(args.length > 0 && (!(sender instanceof Player) || sender.hasPermission(Permissions.INVENTORY_CLEAR_OTHER))) { return Utils.getPlayerNamesStartingWith(args[args.length - 1], sender); } return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/MigrateCommand.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration.MigrationManager; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Locale; public class MigrateCommand extends MinepacksCommand { public MigrateCommand(Minepacks plugin) { super(plugin, "migrate", plugin.getLanguage().getTranslated("Commands.Description.Migrate"), Permissions.MIGRATE, plugin.getLanguage().getCommandAliases("migrate")); } @Override public void execute(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { if(args.length >= 1) { switch(args[0].toLowerCase(Locale.ROOT)) { case "db": case "database": case "storage": migrateDb(sender, args); break; } } else { sender.sendMessage("/" + mainCommandAlias + ' ' + alias + "database"); } } private void migrateDb(final @NotNull CommandSender sender, final @NotNull String[] args) { if(args.length >= 2) { if(args.length >= 3 && args[2].equalsIgnoreCase("start")) { MigrationManager migrationManager = new MigrationManager((Minepacks) getMinepacksPlugin()); migrationManager.migrateDB(args[1], result -> { sender.sendMessage("Minepacks database migration result: " + result.getType().name()); sender.sendMessage(result.getMessage()); }); } else { sender.sendMessage("This process will convert your storage type from " + ((Minepacks) getMinepacksPlugin()).getDatabase().getClass().getName() + " to " + args[1]); sender.sendMessage("Your old data will not be deleted and you can switch back any time in the \"config.yml\" file."); if(args[1].equalsIgnoreCase("mysql")) { sender.sendMessage("Please make sure that you have set the config options \"Host\", \"Database\", \"User\" and \"Password\" to the correct values."); } sender.sendMessage("To start the migration please confirm with: /backpack migrate " + args[0] + ' ' + args[1] + " start"); } } else { sender.sendMessage("/backpacks migrate " + args[0] + " "); } } @Override public List tabComplete(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { return null; } @Override public List getHelp(final @NotNull CommandSender requester) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/OpenCommand.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Message.Placeholder.Processors.GameModePlaceholderProcessor; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Calendar.TimeSpan; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Message.MessageClickEvent; import at.pcgamingfreaks.Message.Placeholder.Processors.FloatPlaceholderProcessor; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; public class OpenCommand extends MinepacksCommand { private final Message messageCooldown, messageWrongGameMode; private final String descriptionOpenOthers, helpParam; private final Minepacks plugin; public OpenCommand(Minepacks plugin) { super(plugin, "open", plugin.getLanguage().getTranslated("Commands.Description.Backpack"), Permissions.USE, false, plugin.getLanguage().getCommandAliases("Open")); this.plugin = plugin; messageCooldown = plugin.getLanguage().getMessage("Ingame.Open.Cooldown").placeholder("TimeLeft", new FloatPlaceholderProcessor(1)).placeholder("TimeSpanLeft"); messageWrongGameMode = plugin.getLanguage().getMessage("Ingame.Open.WrongGameMode").staticPlaceholder("AllowedGameModes", new GameModePlaceholderProcessor(), plugin.getConfiguration().getAllowedGameModes()).placeholder("CurrentGameMode", new GameModePlaceholderProcessor()); descriptionOpenOthers = plugin.getLanguage().getTranslated("Commands.Description.OpenOthers"); helpParam = "<" + plugin.getLanguage().get("Commands.PlayerNameVariable") + ">"; } @Override public void execute(@NotNull CommandSender sender, @NotNull String main, @NotNull String s1, @NotNull String[] args) { if (!(sender instanceof Player)) { handleOpenFromConsole(sender, args); return; } Player player = (Player) sender; if(args.length == 0) { executeSelf(player); } else { executeOther(player, args[0]); } } void executeSelf(Player player) { if(getMinepacksPlugin().isPlayerGameModeAllowed(player)) { if(plugin.getCooldownManager() != null && !player.hasPermission(Permissions.NO_COOLDOWN)) { long cd = plugin.getCooldownManager().getRemainingCooldown(player); if(cd > 0) { TimeSpan ts = TimeSpan.fromMilliseconds(cd); messageCooldown.send(player, cd / 1000f, ts.toString()); return; } plugin.getCooldownManager().setCooldown(player); } plugin.openBackpack(player, player, true); } else { messageWrongGameMode.send(player, player.getGameMode()); } } void executeOther(Player player, String name) { if(player.hasPermission(Permissions.OTHERS)) { OfflinePlayer target = Bukkit.getPlayer(name); if(target == null) { //noinspection deprecation target = Bukkit.getOfflinePlayer(name); } plugin.openBackpack(player, target, player.hasPermission(Permissions.OTHERS_EDIT)); } else { plugin.messageNoPermission.send(player); } } void handleOpenFromConsole(final @NotNull CommandSender sender, final @NotNull String[] names) { int opened = 0; List notOnline = new ArrayList<>(names.length); for(String name : names) { Player target = Bukkit.getPlayer(name); if (target == null) { notOnline.add(name); } else if (target.hasPermission(Permissions.USE)) { opened++; plugin.openBackpack(target, target, true); } } sender.sendMessage("Opened backpack of " + opened + " players." + (notOnline.isEmpty() ? "" : " Not online: " + String.join(", ", notOnline))); } @Override public List tabComplete(@NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { if(args.length > 0 && (!(commandSender instanceof Player) || commandSender.hasPermission(Permissions.OTHERS))) { return Utils.getPlayerNamesStartingWith(args[args.length - 1], commandSender); } return null; } @Override public List getHelp(@NotNull CommandSender requester) { List help = new ArrayList<>(2); help.add(new HelpData(getTranslatedName(), null, getDescription(), MessageClickEvent.ClickEventAction.RUN_COMMAND)); if(requester.hasPermission(Permissions.OTHERS)) { help.add(new HelpData(getTranslatedName(), helpParam, descriptionOpenOthers)); } return help; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/PickupCommand.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.ItemsCollector; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.List; public class PickupCommand extends MinepacksCommand { private final Minepacks plugin; private final Message toggleOn, toggleOff; public PickupCommand(Minepacks plugin) { super(plugin, "pickup", plugin.getLanguage().getTranslated("Commands.Description.Pickup"), Permissions.PICKUP_TOGGLE, true, plugin.getLanguage().getCommandAliases("Pickup")); this.plugin = plugin; toggleOn = plugin.getLanguage().getMessage("Ingame.Pickup.ToggleOn"); toggleOff = plugin.getLanguage().getMessage("Ingame.Pickup.ToggleOff"); } @Override public void execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String s1, @NotNull String[] args) { Player player = (Player) sender; ItemsCollector collector = plugin.getItemsCollector(); if (collector == null) return; if (collector.toggleState(player.getUniqueId())) { toggleOn.send(player); } else { toggleOff.send(player); } } @Override public List tabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String s1, @NotNull String[] strings) { return null; } @Override public boolean canUse(@NotNull CommandSender sender) { return super.canUse(sender) && sender.hasPermission(Permissions.FULL_PICKUP) && sender.hasPermission(Permissions.USE); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/ReloadCommand.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.List; public class ReloadCommand extends MinepacksCommand { private final Message messageReloading, messageReloaded; public ReloadCommand(Minepacks plugin) { super(plugin, "reload", plugin.getLanguage().getTranslated("Commands.Description.Reload"), Permissions.RELOAD, plugin.getLanguage().getCommandAliases("Reload")); // Load messages messageReloading = plugin.getLanguage().getMessage("Ingame.Reload.Reloading"); messageReloaded = plugin.getLanguage().getMessage("Ingame.Reload.Reloaded"); } @Override public void execute(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { messageReloading.send(sender); ((Minepacks) plugin).reload(); messageReloaded.send(sender); } @Override public List tabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/RestoreCommand.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Message.MessageClickEvent; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholders; import at.pcgamingfreaks.Util.StringUtils; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import java.text.SimpleDateFormat; import java.util.*; public class RestoreCommand extends MinepacksCommand { private final Message messageBackupsHeader, messageBackupsFooter, messageBackupEntry, messageUnableToLoadBackup, messageNoUserFound, messageRestored; private final String helpParam; private final SimpleDateFormat dateFormat; private final String[] listCommands; private final int elementsPerPage; public RestoreCommand(Minepacks plugin) { super(plugin, "restore", plugin.getLanguage().getTranslated("Commands.Description.Restore"), Permissions.RESTORE, plugin.getLanguage().getCommandAliases("Restore")); helpParam = "<" + plugin.getLanguage().get("Ingame.Restore.ParameterBackupName") + "> (" + plugin.getLanguage().get("Commands.PlayerNameVariable") + ")"; messageBackupsHeader = plugin.getLanguage().getMessage("Ingame.Restore.Headline").placeholders(Placeholders.PAGE_OPTIONS); messageBackupsFooter = plugin.getLanguage().getMessage("Ingame.Restore.Footer").placeholders(Placeholders.PAGE_OPTIONS); messageBackupEntry = plugin.getLanguage().getMessage("Ingame.Restore.BackupEntry").placeholder("BackupIdentifier").placeholder("BackupDate") .placeholder("BackupPlayerName").placeholder("BackupPlayerUUID").placeholder("MainCommand").placeholder("SubCommand"); messageUnableToLoadBackup = plugin.getLanguage().getMessage("Ingame.Restore.NoValidBackup").placeholder("BackupIdentifier"); messageNoUserFound = plugin.getLanguage().getMessage("Ingame.Restore.NoUserToRestoreToFound"); messageRestored = plugin.getLanguage().getMessage("Ingame.Restore.Restored"); listCommands = plugin.getLanguage().getCommandAliases("ListBackups", "list"); //noinspection ConstantConditions elementsPerPage = plugin.getLanguage().getYaml().getInt("Ingame.Restore.BackupsPerPage", 10); dateFormat = (plugin.getLanguage().get("Ingame.Restore.BackupEntry").contains("{BackupDate}")) ? new SimpleDateFormat(plugin.getLanguage().get("Ingame.Restore.DateFormat")) : null; } @Override public void execute(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { if(args.length == 1 || args.length == 2) { if(StringUtils.arrayContainsIgnoreCase(listCommands, args[0])) { listBackups(sender, mainCommandAlias, alias, args); } else { restore(sender, args); } } else { showHelp(sender, mainCommandAlias); } } @SuppressWarnings("deprecation") private void restore(final @NotNull CommandSender sender, final @NotNull String[] args) { ItemStack[] items = ((Minepacks) getMinepacksPlugin()).getDatabase().loadBackup(args[0]); if(items != null) { OfflinePlayer target = null; if(args.length == 2) { target = plugin.getServer().getOfflinePlayer(args[1]); } else { String[] components = args[0].split("_"); if(components.length == 2) { target = plugin.getServer().getOfflinePlayer(components[0]); } else if(components.length == 3) { if(!components[1].contains("-")) { components[1] = components[1].replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"); } target = plugin.getServer().getOfflinePlayer(UUID.fromString(components[1])); } } if(target == null) { messageNoUserFound.send(sender); return; } getMinepacksPlugin().getBackpack(target, backpack -> { if (backpack.getSize() != items.length) { backpack.clear(); ((Backpack) backpack).setSize(items.length); } backpack.getInventory().setContents(items); backpack.setChanged(); messageRestored.send(sender); }); } else { messageUnableToLoadBackup.send(sender, args[0]); } } private int parsePageNr(final @NotNull CommandSender sender, final @NotNull String[] args) { if(args.length == 2) { try { return StringUtils.parsePageNumber(args[1]); } catch(NumberFormatException ignored) { ((Minepacks) getMinepacksPlugin()).messageNotANumber.send(sender); } } return 0; } private String formatUUID(final @NotNull String uuidString) { if (uuidString.contains("-")) return uuidString; return uuidString.replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"); } private void listBackups(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { int page = parsePageNr(sender, args); ArrayList backups = ((Minepacks) getMinepacksPlugin()).getDatabase().getBackups(); int pages = backups.size() / elementsPerPage + 1; page = Math.min(page, pages - 1); int offset = page * elementsPerPage, end = Math.min(offset + elementsPerPage, backups.size()); String subCom = alias + ' ' + args[0]; messageBackupsHeader.send(sender, page + 1, pages, mainCommandAlias, subCom, page, page + 2); while(offset < end) { String backup = backups.get(offset++), uuid = "No UUID", date = "Unknown"; String[] components = backup.split("_"); if(components.length == 3) uuid = formatUUID(components[1]); if(dateFormat != null && (components.length == 2 || components.length == 3)) { try { date = dateFormat.format(new Date(Long.parseLong(components[components.length - 1]))); } catch(NumberFormatException ignored) {} } messageBackupEntry.send(sender, backup, date, components[0], uuid, mainCommandAlias, alias); } messageBackupsFooter.send(sender, page + 1, pages, mainCommandAlias, subCom, page, page + 2); } @Override public List tabComplete(final @NotNull CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { final String arg = args[args.length - 1].toLowerCase(Locale.ROOT); List autoComplete = null; if(args.length == 1) { List backups = ((Minepacks) getMinepacksPlugin()).getDatabase().getBackups(); autoComplete = new ArrayList<>(); for(String backupId : backups) { if(backupId.toLowerCase(Locale.ROOT).startsWith(arg)) autoComplete.add(backupId); } for(String listCommand : listCommands) { if(listCommand.startsWith(arg)) autoComplete.add(listCommand); } } else if(args.length == 2) { autoComplete = new ArrayList<>(); for(Player player : Bukkit.getOnlinePlayers()) { if(player.getName().toLowerCase(Locale.ROOT).startsWith(arg)) autoComplete.add(player.getName()); } } return autoComplete; } @Override public List getHelp(final @NotNull CommandSender requester) { List help = new ArrayList<>(); help.add(new HelpData(getTranslatedName() + " " + listCommands[0], null, ((Minepacks) getMinepacksPlugin()).getLanguage().getTranslated("Commands.Description.RestoreList"), MessageClickEvent.ClickEventAction.RUN_COMMAND)); help.add(new HelpData(getTranslatedName(), helpParam, getDescription(), MessageClickEvent.ClickEventAction.SUGGEST_COMMAND)); return help; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/ShortcutCommand.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Command.HelpData; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Listener.ItemShortcut; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; public class ShortcutCommand extends MinepacksCommand { private final ItemShortcut itemShortcut; public ShortcutCommand(Minepacks plugin, final @NotNull ItemShortcut itemShortcut) { super(plugin, "shortcut", ""/*plugin.getLanguage().getTranslated("Commands.Description.Shortcut")*/, Permissions.USE, true, plugin.getLanguage().getCommandAliases("Shortcut")); this.itemShortcut = itemShortcut; } @Override public void execute(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { if (args.length == 1 && sender.hasPermission(Permissions.OTHERS)) { Player p = Bukkit.getPlayer(args[0]); if (p != null && p.hasPermission(Permissions.USE)) itemShortcut.addItem(p); } else { itemShortcut.addItem((Player) sender); } } @Override public List tabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } @Override public @Nullable List getHelp(@NotNull CommandSender requester) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/SortCommand.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper.InventoryCompressor; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.List; public class SortCommand extends MinepacksCommand { private final Message messageSorted; public SortCommand(Minepacks plugin) { super(plugin, "sort", plugin.getLanguage().getTranslated("Commands.Description.Sort"), Permissions.SORT, true, plugin.getLanguage().getCommandAliases("Sort")); messageSorted = plugin.getLanguage().getMessage("Ingame.Sort.Sorted"); } @Override public void execute(final @NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { final Player player = (Player) commandSender; getMinepacksPlugin().getBackpack(player, backpack -> { InventoryCompressor compressor = new InventoryCompressor(backpack.getInventory().getContents()); if(!compressor.sort().isEmpty()) { plugin.getLogger().warning("Failed to sort backpack!"); //this should not happen return; } backpack.getInventory().setContents(compressor.getTargetStacks()); backpack.setChanged(); messageSorted.send(player); }); } @Override public List tabComplete(@NotNull CommandSender commandSender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/UpdateCommand.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import at.pcgamingfreaks.Minepacks.MagicValues; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.List; public class UpdateCommand extends MinepacksCommand { private final Message messageCheckingForUpdates, messageUpdated, messageNoUpdate, messageUpdateFail, messageUpdateAvailable; public UpdateCommand(Minepacks plugin) { super(plugin, "update", plugin.getLanguage().getTranslated("Commands.Description.Update"), Permissions.UPDATE, plugin.getLanguage().getCommandAliases("Update")); messageCheckingForUpdates = plugin.getLanguage().getMessage("Ingame.Update.CheckingForUpdates"); messageUpdated = plugin.getLanguage().getMessage("Ingame.Update.Updated"); messageNoUpdate = plugin.getLanguage().getMessage("Ingame.Update.NoUpdate"); messageUpdateFail = plugin.getLanguage().getMessage("Ingame.Update.UpdateFail"); messageUpdateAvailable = plugin.getLanguage().getMessage("Ingame.Update.UpdateAvailable"); } @Override public void execute(@NotNull final CommandSender sender, final @NotNull String mainCommandAlias, final @NotNull String alias, final @NotNull String[] args) { if(MCVersion.isNewerOrEqualThan(MCVersion.getFromVersionName(MagicValues.MIN_MC_VERSION_FOR_UPDATES))) { messageCheckingForUpdates.send(sender); /*if_not[STANDALONE]*/ ((at.pcgamingfreaks.PluginLib.Bukkit.PluginLib) at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance()).getUpdater().update(); // Make the PluginLib check for updates too /*end[STANDALONE]*/ ((Minepacks) plugin).update(result -> { switch(result) { case SUCCESS: messageUpdated.send(sender); break; case NO_UPDATE: messageNoUpdate.send(sender); break; case UPDATE_AVAILABLE: messageUpdateAvailable.send(sender); break; default: messageUpdateFail.send(sender); break; } }); } else { sender.sendMessage(ChatColor.RED + "There are no more updates for Minecraft 1.7. If you would like to use new features please update your Minecraft version."); } } @Override public List tabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Command/VersionCommand.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Command; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.List; public class VersionCommand extends MinepacksCommand { private final String minepacksVersion; public VersionCommand(Minepacks plugin) { super(plugin, "version", plugin.getLanguage().getTranslated("Commands.Description.Version"), Permissions.VERSION, plugin.getLanguage().getCommandAliases("Version")); minepacksVersion = plugin.getDescription().getName() + ": " + plugin.getDescription().getVersion(); } @Override public void execute(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { sender.sendMessage("##### Start Minepacks version info #####"); sender.sendMessage(minepacksVersion); /*if_not[STANDALONE]*/ sender.sendMessage("PCGF PluginLib: " + at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getVersion()); /*end[STANDALONE]*/ sender.sendMessage("Server: " + plugin.getServer().getVersion()); sender.sendMessage("Java: " + System.getProperty("java.version")); sender.sendMessage("##### End Minepacks version info #####"); } @Override public List tabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String[] args) { return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/CooldownManager.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class CooldownManager extends CancellableRunnable implements Listener { private final Minepacks plugin; private final Map cooldowns = new HashMap<>(); private final long cooldown; private final boolean syncCooldown, addOnJoin, clearOnLeave; public CooldownManager(Minepacks plugin) { this.plugin = plugin; cooldown = plugin.getConfiguration().getCommandCooldown(); syncCooldown = plugin.getConfiguration().isCommandCooldownSyncEnabled(); addOnJoin = plugin.getConfiguration().isCommandCooldownAddOnJoinEnabled(); clearOnLeave = plugin.getConfiguration().isCommandCooldownClearOnLeaveEnabled(); plugin.getServer().getPluginManager().registerEvents(this, plugin); schedule(); } public void close() { cancel(); HandlerList.unregisterAll(this); } public void setCooldown(@NotNull Player player) { final long cooldownTime = System.currentTimeMillis() + cooldown; if(syncCooldown) { plugin.getDatabase().syncCooldown(player, cooldownTime); } cooldowns.put(player.getUniqueId(), cooldownTime); } @SuppressWarnings("unused") public boolean isInCooldown(@NotNull Player player) { return cooldowns.getOrDefault(player.getUniqueId(), 0L) > System.currentTimeMillis(); } public long getRemainingCooldown(@NotNull Player player) { long cd = cooldowns.getOrDefault(player.getUniqueId(), 0L); if(cd > System.currentTimeMillis()) { return cd - System.currentTimeMillis(); } return 0; } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoinEvent(PlayerJoinEvent event) { if(syncCooldown) { final UUID uuid = event.getPlayer().getUniqueId(); cooldowns.put(uuid, System.currentTimeMillis() + cooldown); // Temporary cooldown till the data is loaded from the database plugin.getDatabase().getCooldown(event.getPlayer(), dbCooldownTime -> cooldowns.put(uuid, dbCooldownTime)); } else if(addOnJoin) { setCooldown(event.getPlayer()); } } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerLeaveEvent(PlayerQuitEvent event) { if(clearOnLeave) cooldowns.remove(event.getPlayer().getUniqueId()); } @Override public void run() { cooldowns.entrySet().removeIf(entry -> entry.getValue() < System.currentTimeMillis()); } @Override public void schedule() { task = getScheduler().runTimer(this::run, plugin.getConfiguration().getCommandCooldownCleanupInterval(), plugin.getConfiguration().getCommandCooldownCleanupInterval()); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Config.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.MinecraftMaterial; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.Config.Configuration; import at.pcgamingfreaks.Config.ILanguageConfiguration; import at.pcgamingfreaks.Config.YamlFileManager; import at.pcgamingfreaks.ConsoleColor; import at.pcgamingfreaks.Database.DatabaseConnectionConfiguration; import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper.OldFileUpdater; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.ShrinkApproach; import at.pcgamingfreaks.Minepacks.MagicValues; import at.pcgamingfreaks.Reflection; import at.pcgamingfreaks.Version; import org.bukkit.*; import org.jetbrains.annotations.NotNull; import java.io.FileNotFoundException; import java.lang.reflect.Field; import java.util.*; import java.util.logging.Level; public class Config extends Configuration implements DatabaseConnectionConfiguration, ILanguageConfiguration { private static final Version CONFIG_VERSION = new Version(MagicValues.CONFIG_VERSION), PRE_V2_VERSION = new Version(20); public Config(Minepacks plugin) { super(plugin, CONFIG_VERSION); } @Override protected void doUpdate() { // Nothing to update yet } @Override protected void doUpgrade(@NotNull YamlFileManager oldConfig) { if(oldConfig.getVersion().olderThan(PRE_V2_VERSION)) // Pre V2.0 config file { OldFileUpdater.updateConfig(oldConfig.getYamlE(), getConfigE()); } else { Map remappedKeys = new HashMap<>(); if(oldConfig.getVersion().olderOrEqualThan(new Version(23))) remappedKeys.put("ItemFilter.Materials", "ItemFilter.Blacklist"); if(oldConfig.getVersion().olderOrEqualThan(new Version(28))) remappedKeys.put("Misc.AutoUpdate.Enabled", "Misc.AutoUpdate"); if(oldConfig.getVersion().olderOrEqualThan(new Version(30))) { remappedKeys.put("WorldSettings.FilteredWorlds", "WorldSettings.Blacklist"); remappedKeys.put("WorldSettings.BockMode", "WorldSettings.BlacklistMode"); } if(oldConfig.getVersion().olderOrEqualThan(new Version(33))) remappedKeys.put("Database.Cache.UnCache.Strategy", "Database.Cache.UnCache.Strategie"); Collection keysToKeep = oldConfig.getYamlE().getKeysFiltered("Database\\.SQL\\.(MaxLifetime|IdleTimeout)"); keysToKeep.addAll(oldConfig.getYamlE().getKeysFiltered("Database\\.Tables\\.Fields\\..+")); doUpgrade(oldConfig, remappedKeys, keysToKeep); } } //region getter //region Database getter public int getAutoCleanupMaxInactiveDays() { return getConfigE().getInt("Database.AutoCleanup.MaxInactiveDays", -1); } public String getDatabaseType() { return getConfigE().getString("Database.Type", "sqlite").toLowerCase(Locale.ENGLISH); } public void setDatabaseType(String type) { getConfigE().set("Database.Type", type); try { save(); } catch(FileNotFoundException e) { logger.log(Level.SEVERE, "Failed to set database type", e); } } public String getUserTable() { return getConfigE().getString("Database.Tables.User", "backpack_players"); } public String getBackpackTable() { return getConfigE().getString("Database.Tables.Backpack", "backpacks"); } public String getCooldownTable() { return getConfigE().getString("Database.Tables.Cooldown", "backpack_cooldowns"); } public String getDBFields(String sub, String def) { return getConfigE().getString("Database.Tables.Fields." + sub, def); } public boolean useOnlineUUIDs() { String type = getConfigE().getString("Database.UUID_Type", "auto").toLowerCase(Locale.ENGLISH); if(type.equals("auto")) { if(isBungeeCordModeEnabled()) { Boolean detectedOnlineMode = Utils.getBungeeOrVelocityOnlineMode(); if (detectedOnlineMode != null) { logger.log(Level.INFO, "Detected online mode in paper config: {0}", detectedOnlineMode); return detectedOnlineMode; } logger.warning("When using BungeeCord please make sure to set the UUID_Type config option explicitly!"); } return Bukkit.getServer().getOnlineMode(); } return type.equals("online"); } public boolean getUseUUIDSeparators() { return getConfigE().getBoolean("Database.UseUUIDSeparators", false); } public boolean isForceSaveOnUnloadEnabled() { return getConfigE().getBoolean("Database.ForceSaveOnUnload", false); } public String getUnCacheStrategy() { return getConfigE().getString("Database.Cache.UnCache.Strategy", "interval").toLowerCase(Locale.ENGLISH); } public long getUnCacheInterval() { return getConfigE().getLong("Database.Cache.UnCache.Interval", 600) * 20L; } public long getUnCacheDelay() { return getConfigE().getLong("Database.Cache.UnCache.Delay", 600) * 20L; } //endregion public String getBPTitleOther() { return ChatColor.translateAlternateColorCodes('&', getConfigE().getString("BackpackTitleOther", "{OwnerName} Backpack").replace("%", "%%").replace("{OwnerName}", "%s")); } public String getBPTitle() { return ChatColor.translateAlternateColorCodes('&', getConfigE().getString("BackpackTitle", "Backpack").replace("%", "%%").replace("{OwnerName}", "%s")); } public boolean useDynamicBPTitle() { return getConfigE().getBoolean("Database.UseDynamicTitle", true); } public boolean getDropOnDeath() { return getConfigE().getBoolean("DropOnDeath", true); } public boolean getHonorKeepInventoryOnDeath() { return getConfigE().getBoolean("HonorKeepInventoryOnDeath", false); } public int getBackpackMaxSize() { int size = getConfigE().getInt("MaxSize", 6); if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_14)) size = Math.min(6, size); if(size > 6) { logger.info("Starting with MC 1.14 backpacks with more than 6 rows will no longer be possible. A feature to allow bigger backpacks through multiple pages is currently in development."); } return Math.max(1, size); } public ShrinkApproach getShrinkApproach() { if(MCVersion.isOlderThan(MCVersion.MC_1_8)) return ShrinkApproach.FAST; String approach = getConfigE().getString("ShrinkApproach", "SORT"); try { return ShrinkApproach.valueOf(approach.toUpperCase(Locale.ENGLISH)); } catch(IllegalArgumentException ignored) { logger.log(Level.WARNING, "Unknown ShrinkApproach \"{0}\"!", approach); return ShrinkApproach.SORT; } } //region Misc getters public boolean useUpdater() { return (MCVersion.isNewerOrEqualThan(MCVersion.getFromVersionName(MagicValues.MIN_MC_VERSION_FOR_UPDATES))) && getConfigE().getBoolean("Misc.AutoUpdate.Enabled", getConfigE().getBoolean("Misc.AutoUpdate", true)); } public String getUpdateChannel() { String channel = getConfigE().getString("Misc.AutoUpdate.Channel", "Release"); if("Release".equals(channel) || "Master".equals(channel) || "Dev".equals(channel)) { return channel; } else logger.log(Level.INFO, "Unknown update Channel: {0}", channel); return null; } public boolean isBungeeCordModeEnabled() { boolean useBungee = getConfigE().getBoolean("Misc.UseBungeeCord", false); boolean runsProxy = Utils.detectBungeeCord() || Utils.detectVelocity(); boolean shareableDB = getDatabaseType().equals("mysql") || getDatabaseType().equals("global"); if(useBungee && !runsProxy) { logger.warning("You have BungeeCord enabled for the plugin, but it looks like you have not enabled it in your spigot.yml! You probably should check your configuration."); } else if(!useBungee && runsProxy && shareableDB) { logger.warning("Your server is running behind a BungeeCord server. If you are using the plugin on more than one server with a shared database, please make sure to also enable the 'UseBungeeCord' config option."); } else if(useBungee && !shareableDB) { logger.info("You have enabled BungeeCord mode for the plugin, but are not using a shared MySQL database."); return false; // No need to enable BungeeCord mode if the database does not support it } return useBungee; } //endregion public long getCommandCooldown() { return getConfigE().getInt("Cooldown.Command", -1) * 1000L; } public boolean isCommandCooldownSyncEnabled() { return getConfigE().getBoolean("Cooldown.Sync", false); } public boolean isCommandCooldownClearOnLeaveEnabled() { return getConfigE().getBoolean("Cooldown.ClearOnLeave", false); } public boolean isCommandCooldownAddOnJoinEnabled() { return getConfigE().getBoolean("Cooldown.AddOnJoin", true); } public long getCommandCooldownCleanupInterval() { return getConfigE().getInt("Cooldown.CleanupInterval", 600) * 20L; } public Collection getAllowedGameModes() { Collection gameModes = new HashSet<>(); for(String string : getConfigE().getStringList("AllowedGameModes", new LinkedList<>())) { GameMode gm = null; try { //noinspection deprecation gm = GameMode.getByValue(Integer.parseInt(string)); } catch(NumberFormatException ignored) {} if(gm == null) { try { gm = GameMode.valueOf(string.toUpperCase(Locale.ROOT)); } catch(IllegalArgumentException ignored) { logger.warning("Unknown game-mode '" + string + "'"); } } if(gm != null) { gameModes.add(gm); } } if(gameModes.isEmpty()) { logger.info("No game-mode's allowed, allowing: " + GameMode.SURVIVAL.name()); gameModes.add(GameMode.SURVIVAL); } return gameModes; } //region Full inventory handling public boolean getFullInvCollect() { return getConfigE().getBoolean("FullInventory.CollectItems", false); } public long getFullInvCheckInterval() { return getConfigE().getInt("FullInventory.CheckInterval", 1) * 20L; // in seconds } public double getFullInvRadius() { return getConfigE().getDouble("FullInventory.CollectRadius", 1.5); // in blocks } public boolean isFullInvToggleAllowed() { return getConfigE().getBoolean("FullInventory.IsToggleAllowed", false); } public boolean isFullInvEnabledOnJoin() { return getFullInvCollect(); } //endregion //region Shulkerboxes public boolean isShulkerboxesPreventInBackpackEnabled() { // Shulkerboxes are only available in MC 1.11 and newer return MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11) && getConfigE().getBoolean("Shulkerboxes.PreventInBackpack", true); } public boolean isShulkerboxesDisable() { // Shulkerboxes are only available in MC 1.11 and newer return MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11) && getConfigE().getBoolean("Shulkerboxes.DisableShulkerboxes", false); } public boolean isShulkerboxesExistingDropEnabled() { return getConfigE().getString("Shulkerboxes.Existing", "Ignore").equalsIgnoreCase("Destroy"); } public boolean isShulkerboxesExistingDestroyEnabled() { return getConfigE().getString("Shulkerboxes.Existing", "Ignore").equalsIgnoreCase("Destroy") || getConfigE().getString("Shulkerboxes.Existing", "Ignore").equalsIgnoreCase("Remove"); } //endregion //region Item filter public boolean isItemFilterEnabledNoShulker() { return getConfigE().getBoolean("ItemFilter.Enabled", false); } public boolean isItemFilterEnabled() { return isItemFilterEnabledNoShulker() || getConfigE().getBoolean("Shulkerboxes.PreventInBackpack", true); } public Collection getItemFilterMaterials() { if(!isItemFilterEnabledNoShulker()) return new LinkedList<>(); List stringMaterialList = getConfigE().getStringList("ItemFilter.Materials", new LinkedList<>()); if(isItemFilterModeWhitelist()) stringMaterialList.add("air"); Collection blacklist = new LinkedList<>(); for(String item : stringMaterialList) { MinecraftMaterial mat = MinecraftMaterial.fromInput(item); if(mat != null) blacklist.add(mat); } return blacklist; } public Set getItemFilterNames() { if(!isItemFilterEnabledNoShulker()) return new HashSet<>(); Set names = new HashSet<>(); getConfigE().getStringList("ItemFilter.Names", new LinkedList<>()).forEach(name -> names.add(ChatColor.translateAlternateColorCodes('&', name))); return names; } public Set getItemFilterLore() { if(!isItemFilterEnabledNoShulker()) return new HashSet<>(); Set loreSet = new HashSet<>(); getConfigE().getStringList("ItemFilter.Lore", new LinkedList<>()).forEach(lore -> loreSet.add(ChatColor.translateAlternateColorCodes('&', lore))); return loreSet; } public boolean isItemFilterModeWhitelist() { return getConfigE().getString("ItemFilter.Mode", "blacklist").toLowerCase(Locale.ENGLISH).equals("whitelist") && isItemFilterEnabledNoShulker(); } //endregion //region World settings public boolean isWorldWhitelistMode() { return getConfigE().getString("WorldSettings.FilterType", "blacklist").equalsIgnoreCase("whitelist"); } public Set getWorldFilteredList() { Set worldList = new HashSet<>(); for(String world : getConfigE().getStringList("WorldSettings.FilteredWorlds", new ArrayList<>(0))) { worldList.add(world.toLowerCase(Locale.ROOT)); } return worldList; } public Set getWorldBlacklist() { if(isWorldWhitelistMode()) { Set whitelist = getWorldFilteredList(), blacklist = new HashSet<>(); for(World world : Bukkit.getServer().getWorlds()) { String worldName = world.getName().toLowerCase(Locale.ROOT); if(!whitelist.contains(worldName)) blacklist.add(worldName); } return blacklist; } else return getWorldFilteredList(); } public WorldBlacklistMode getWorldBlockMode() { String mode = getConfigE().getString("WorldSettings.BlockMode", "Message"); WorldBlacklistMode blacklistMode = WorldBlacklistMode.Message; try { blacklistMode = WorldBlacklistMode.valueOf(mode); } catch(IllegalArgumentException ignored) { logger.warning(ConsoleColor.YELLOW + "Unsupported mode \"" + mode + "\" for option \"WorldSettings.BlockMode\"" + ConsoleColor.RESET); } return blacklistMode; } //endregion //region ItemShortcut settings public boolean isItemShortcutEnabled() { return MCVersion.isNewerOrEqualThan(MCVersion.MC_1_8) && getConfigE().getBoolean("ItemShortcut.Enabled", true); } public String getItemShortcutItemName() { return getConfigE().getString("ItemShortcut.ItemName", "&eBackpack"); } public String getItemShortcutHeadValue() { return getConfigE().getString("ItemShortcut.HeadTextureValue", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGRjYzZlYjQwZjNiYWRhNDFlNDMzOTg4OGQ2ZDIwNzQzNzU5OGJkYmQxNzVjMmU3MzExOTFkNWE5YTQyZDNjOCJ9fX0="); } public boolean isItemShortcutImproveDeathChestCompatibilityEnabled() { return getConfigE().getBoolean("ItemShortcut.ImproveDeathChestCompatibility", false); } public boolean isItemShortcutBlockAsHatEnabled() { return getConfigE().getBoolean("ItemShortcut.BlockAsHat", false); } public boolean isItemShortcutRightClickOnContainerAllowed() { return getConfigE().getBoolean("ItemShortcut.OpenContainerOnRightClick", false) && MCVersion.isNewerOrEqualThan(MCVersion.MC_1_13); } public int getItemShortcutPreferredSlotId() { return getConfigE().getInt("ItemShortcut.PreferredSlotId", -1); } public boolean getItemShortcutBlockItemFromMoving() { return getConfigE().getBoolean("ItemShortcut.BlockItemFromMoving", false); } //endregion //region Sound settings private Sound getSound(String option, String autoValue) { if(!getConfigE().getBoolean("Sound.Enabled", true)) return null; String soundName = getConfigE().getString("Sound." + option, "auto").toUpperCase(Locale.ENGLISH); if(soundName.equals("AUTO")) soundName = autoValue; if(soundName.equals("DISABLED") || soundName.equals("FALSE")) return null; try { if (MCVersion.isNewerOrEqualThan(MCVersion.MC_1_21)) { Field f = Reflection.getField(Sound.class, soundName); if (f != null) return (Sound) f.get(null); } else { return Sound.valueOf(soundName); } } catch(Exception ignored) { logger.warning("Unknown sound: " + soundName); } return null; } private static final @NotNull String DEFAULT_SOUND_OPEN = MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11) ? "BLOCK_SHULKER_BOX_OPEN" : (MCVersion.isNewerOrEqualThan(MCVersion.MC_1_9_2) ? "BLOCK_CHEST_OPEN" : "CHEST_OPEN"); private static final @NotNull String DEFAULT_SOUND_CLOSE = MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11) ? "BLOCK_SHULKER_BOX_CLOSE" : (MCVersion.isNewerOrEqualThan(MCVersion.MC_1_9_2) ? "BLOCK_CHEST_CLOSE" : "CHEST_CLOSE"); public Sound getOpenSound() { return getSound("OpenSound", DEFAULT_SOUND_OPEN); } public Sound getCloseSound() { return getSound("CloseSound", DEFAULT_SOUND_CLOSE); } //endregion //region InventoryManagement settings public boolean isInventoryManagementClearCommandEnabled() { return getConfigE().getBoolean("InventoryManagement.ClearCommand.Enabled", true); } //endregion //endregion } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Database.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.ConsoleColor; import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider; import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies.OnDisconnect; import at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies.UnCacheStrategy; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileOutputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; public abstract class Database implements Listener { public static final String MESSAGE_UNKNOWN_DB_TYPE = ConsoleColor.RED + "Unknown database type \"%s\"!" + ConsoleColor.RESET; protected final Minepacks plugin; protected final InventorySerializer itsSerializer; protected final boolean onlineUUIDs, bungeeCordMode, forceSaveOnUnload; protected boolean useUUIDSeparators, asyncSave = true; protected long maxAge; private final Map backpacks = new ConcurrentHashMap<>(); private final UnCacheStrategy unCacheStrategy; private final File backupFolder; public Database(Minepacks mp) { plugin = mp; itsSerializer = new InventorySerializer(plugin.getLogger()); useUUIDSeparators = plugin.getConfiguration().getUseUUIDSeparators(); onlineUUIDs = plugin.getConfiguration().useOnlineUUIDs(); bungeeCordMode = plugin.getConfiguration().isBungeeCordModeEnabled(); forceSaveOnUnload = plugin.getConfiguration().isForceSaveOnUnloadEnabled(); maxAge = plugin.getConfiguration().getAutoCleanupMaxInactiveDays(); unCacheStrategy = bungeeCordMode ? new OnDisconnect(this) : UnCacheStrategy.getUnCacheStrategy(this); backupFolder = new File(this.plugin.getDataFolder(), "backups"); if(!backupFolder.exists() && !backupFolder.mkdirs()) mp.getLogger().info("Failed to create backups folder."); } public void init() { plugin.getServer().getPluginManager().registerEvents(this, plugin); } public void close() { HandlerList.unregisterAll(this); asyncSave = false; backpacks.forEach((key, value) -> { if (forceSaveOnUnload) { value.setChanged(); } value.closeAll(); }); backpacks.clear(); unCacheStrategy.close(); } public static @Nullable Database getDatabase(Minepacks plugin) { try { String dbType = plugin.getConfiguration().getDatabaseType(); ConnectionProvider connectionProvider = null; if(dbType.equals("shared") || dbType.equals("external") || dbType.equals("global")) { /*if[STANDALONE] plugin.getLogger().warning(ConsoleColor.RED + "The shared database connection option is not available in standalone mode!" + ConsoleColor.RESET); return null; else[STANDALONE]*/ at.pcgamingfreaks.PluginLib.Database.DatabaseConnectionPool pool = at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getDatabaseConnectionPool(); if(pool == null) { plugin.getLogger().warning(ConsoleColor.RED + "The shared connection pool is not initialized correctly!" + ConsoleColor.RESET); return null; } dbType = pool.getDatabaseType().toLowerCase(Locale.ROOT); connectionProvider = pool.getConnectionProvider(); /*end[STANDALONE]*/ } Database database; switch(dbType) { case "mysql": database = new MySQL(plugin, connectionProvider); break; case "sqlite": database = new SQLite(plugin, connectionProvider); break; case "flat": case "file": case "files": database = new Files(plugin); break; default: plugin.getLogger().warning(String.format(MESSAGE_UNKNOWN_DB_TYPE, plugin.getConfiguration().getDatabaseType())); return null; } database.init(); return database; } catch(IllegalStateException ignored) {} catch(Exception e) { plugin.getLogger().log(Level.SEVERE, "Failed to initialize database.", e); } return null; } public void backup(@NotNull Backpack backpack) { writeBackup(backpack.getOwner().getName(), getPlayerFormattedUUID(backpack.getOwnerId()), itsSerializer.getUsedSerializer(), itsSerializer.serialize(backpack.getInventory())); } protected void writeBackup(@Nullable String userName, @NotNull String userIdentifier, final int usedSerializer, final byte[] data) { if(userIdentifier.equalsIgnoreCase(userName)) userName = null; if(userName != null) userIdentifier = userName + "_" + userIdentifier; final File save = new File(backupFolder, userIdentifier + "_" + System.currentTimeMillis() + Files.EXT); try(FileOutputStream fos = new FileOutputStream(save)) { fos.write(usedSerializer); fos.write(data); plugin.getLogger().info("Backup of the backpack has been created: " + save.getAbsolutePath()); } catch(Exception e) { plugin.getLogger().warning(ConsoleColor.RED + "Failed to write backup! Error: " + e.getMessage() + ConsoleColor.RESET); } } public @Nullable ItemStack[] loadBackup(final String backupName) { File backup = new File(backupFolder, backupName + Files.EXT); return Files.readFile(itsSerializer, backup, plugin.getLogger()); } public ArrayList getBackups() { File[] files = backupFolder.listFiles((dir, name) -> name.endsWith(Files.EXT)); if(files != null) { ArrayList backups = new ArrayList<>(files.length); for(File file : files) { if(!file.isFile()) continue; backups.add(file.getName().replaceAll(Files.EXT_REGEX, "")); } return backups; } return new ArrayList<>(); } protected String getPlayerFormattedUUID(OfflinePlayer player) { return getPlayerFormattedUUID(player.getUniqueId()); } protected String getPlayerFormattedUUID(UUID uuid) { return (useUUIDSeparators) ? uuid.toString() : uuid.toString().replace("-", ""); } public @NotNull Collection getLoadedBackpacks() { return backpacks.values(); } /** * Gets a backpack for a player. This only includes backpacks that are cached! Do not use it unless you are sure that you only want to use cached data! * * @param player The player whose backpack should be retrieved. * @return The backpack for the player. null if the backpack is not in the cache. */ public @Nullable Backpack getBackpack(@Nullable OfflinePlayer player) { return (player == null) ? null : backpacks.get(player.getUniqueId()); } public void getBackpack(final OfflinePlayer player, final Callback callback, final boolean createNewOnFail) { if(player == null || player.getClass().getName().contains("NPC")) { return; } Backpack lbp = backpacks.get(player.getUniqueId()); if(lbp == null) { loadBackpack(player, new Callback() { @Override public void onResult(Backpack backpack) { backpacks.put(player.getUniqueId(), backpack); callback.onResult(backpack); } @Override public void onFail() { if(createNewOnFail) { Backpack backpack = new Backpack(player); backpacks.put(player.getUniqueId(), backpack); callback.onResult(backpack); } else { callback.onFail(); } } }); } else { callback.onResult(lbp); } } public void getBackpack(final OfflinePlayer player, final Callback callback) { getBackpack(player, callback, true); } public void unloadBackpack(Backpack backpack) { if (forceSaveOnUnload) { backpack.forceSave(); } else { backpack.save(); } backpacks.remove(backpack.getOwnerId()); } public void asyncLoadBackpack(final OfflinePlayer player) { if(player != null && backpacks.get(player.getUniqueId()) == null) { loadBackpack(player, new Callback() { @Override public void onResult(Backpack backpack) { backpacks.put(player.getUniqueId(), backpack); } @Override public void onFail() { backpacks.put(player.getUniqueId(), new Backpack(player)); } }); } } @EventHandler public void onPlayerLoginEvent(PlayerJoinEvent event) { updatePlayerAndLoadBackpack(event.getPlayer()); } // DB Functions public void updatePlayerAndLoadBackpack(Player player) { updatePlayer(player); if(!bungeeCordMode) asyncLoadBackpack(player); } public abstract void updatePlayer(Player player); public abstract void saveBackpack(Backpack backpack); public void syncCooldown(Player player, long time) {} public void getCooldown(final Player player, final Callback callback) {} protected abstract void loadBackpack(final OfflinePlayer player, final Callback callback); } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Files.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.UUID.UuidConverter; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; public class Files extends Database { public static final String EXT = ".backpack", EXT_REGEX = "\\.backpack", FOLDER_NAME = "backpacks"; private final File saveFolder; private final UuidConverter converter; public Files(Minepacks plugin) { super(plugin); converter = new UuidConverter(plugin.getLogger()); maxAge *= 24 * 3600000L; saveFolder = new File(this.plugin.getDataFolder(), FOLDER_NAME); if(!saveFolder.exists()) { if(!saveFolder.mkdirs()) { plugin.getLogger().warning("Failed to create save folder (" + saveFolder.getAbsolutePath() + ")."); } } else { checkFiles(); } } @Override public void updatePlayer(Player player) { // Files are stored with the users name or the uuid, there is no reason to update anything } private String getUuidFromFileName(String fileName) { String name = fileName.substring(0, fileName.length() - EXT.length()); UUID uuid = (onlineUUIDs) ? converter.getUUID(name, true) : UuidConverter.getOfflineModeUUID(name); return getPlayerFormattedUUID(uuid); } private void tryRename(File file, File newFileName) { if (!file.renameTo(newFileName)) { plugin.getLogger().log(Level.WARNING, () -> "Failed to rename file (" + file.getAbsolutePath() + " to " + newFileName.getAbsolutePath() + ")."); } } private void checkFiles() { File[] allFiles = saveFolder.listFiles((dir, name) -> name.endsWith(EXT)); if(allFiles == null) return; for (File file : allFiles) { if(maxAge > 0 && System.currentTimeMillis() - file.lastModified() > maxAge) // Check if the file is older than x days { if(!file.delete()) { plugin.getLogger().warning("Failed to delete file (" + file.getAbsolutePath() + ")."); } continue; // We don't have to check if the file name is correct because we have the deleted the file } int len = file.getName().length() - EXT.length(); if(len <= 16) // It's a player name { tryRename(file, new File(saveFolder, getUuidFromFileName(file.getName()) + EXT)); } else // It's a UUID { if(file.getName().contains("-")) { if(!useUUIDSeparators) { tryRename(file, new File(saveFolder, file.getName().replaceAll("-", ""))); } } else if(useUUIDSeparators) { tryRename(file, new File(saveFolder, file.getName().replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})" + EXT_REGEX, "$1-$2-$3-$4-$5" + EXT))); } } } } private String getFileName(UUID uuid) { return getPlayerFormattedUUID(uuid) + EXT; } // DB Functions @Override public void saveBackpack(Backpack backpack) { File save = new File(saveFolder, getFileName(backpack.getOwnerId())); try(FileOutputStream fos = new FileOutputStream(save)) { fos.write(itsSerializer.getUsedSerializer()); fos.write(itsSerializer.serialize(backpack.getInventory())); fos.flush(); } catch(Exception e) { plugin.getLogger().log(Level.SEVERE, "Failed to save backpack.", e); } } @Override protected void loadBackpack(final OfflinePlayer player, final Callback callback) { //TODO this needs to be done async! File save = new File(saveFolder, getFileName(player.getUniqueId())); ItemStack[] itemStacks = readFile(itsSerializer, save, plugin.getLogger()); if(itemStacks != null) { callback.onResult(new Backpack(player, itemStacks, -1)); } else { callback.onFail(); } } protected static @Nullable ItemStack[] readFile(@NotNull InventorySerializer itsSerializer, @NotNull File file, @NotNull Logger logger) { if(file.exists()) { try(FileInputStream fis = new FileInputStream(file)) { int version = fis.read(); byte[] out = new byte[(int) (file.length() - 1)]; int readCount = fis.read(out); if(file.length() - 1 != readCount) logger.warning("Problem reading file, read " + readCount + " of " + (file.length() - 1) + " bytes."); return itsSerializer.deserialize(out, version); } catch(Exception e) { logger.log(Level.WARNING, "Failed to read backpack.", e); } } return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Helper/InventoryCompressor.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper; import lombok.Getter; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; public class InventoryCompressor { @Getter private ItemStack[] targetStacks, inputStacks; private int filled = 0; private ItemStack lastStack = null; @Getter private List toMuch; public InventoryCompressor(ItemStack[] stacks) { this(stacks, stacks.length); } public InventoryCompressor(ItemStack[] stacks, int targetSize) { inputStacks = stacks; targetStacks = new ItemStack[targetSize]; toMuch = new ArrayList<>(inputStacks.length - targetStacks.length); } public InventoryCompressor(ItemStack[] input, ItemStack[] output) { inputStacks = input; targetStacks = output; toMuch = new ArrayList<>(inputStacks.length - targetStacks.length); } public List sort() { for(int i = 0; i < inputStacks.length; i++) { ItemStack stack = inputStacks[i]; if(stack == null || stack.getType() == Material.AIR || stack.getAmount() < 1) continue; add(stack); move(stack, i+1); } return toMuch; } private void move(ItemStack stack, int start) { // Search items that are the same int differentMetaStart = -1; for(int i = start; i < inputStacks.length; i++) { ItemStack stack2 = inputStacks[i]; if(stack2 == null || stack2.getType() == Material.AIR || stack2.getAmount() < 1) continue; if(stack.isSimilar(stack2)) { add(stack2); // Add item to sorted array inputStacks[i] = null; // Remove item from input } else if(differentMetaStart == -1 && stack.getType() == stack2.getType()) { // Same material but different meta differentMetaStart = i; } } if(differentMetaStart >= 0) move(inputStacks[differentMetaStart], differentMetaStart); } private void add(ItemStack stack) { if(stack.isSimilar(lastStack) && lastStack.getAmount() < lastStack.getMaxStackSize()) { // There is still space on the last stack, try to add it int free = lastStack.getMaxStackSize() - lastStack.getAmount(); int place = Math.min(free, stack.getAmount()); lastStack.setAmount(lastStack.getAmount() + place); stack.setAmount(stack.getAmount() - place); } if(stack.getAmount() < 1) return; if(filled == targetStacks.length) { // The new item stack is full, add it to overfill list toMuch.add(stack); } else { // Add the rest to the new inventory targetStacks[filled++] = stack; lastStack = stack; } } public List compress() { for(ItemStack stack : inputStacks) { if(stack == null || stack.getType() == Material.AIR || stack.getAmount() < 1) continue; tryToStack(stack); if(stack.getAmount() == 0) continue; if(filled == targetStacks.length) { toMuch.add(stack); } else { targetStacks[filled++] = stack; } } return toMuch; } private void tryToStack(ItemStack stack) { if(stack.getAmount() >= stack.getMaxStackSize()) return; for(int i = 0; i < filled && stack.getAmount() > 0; i++) { if(stack.isSimilar(targetStacks[i]) && targetStacks[i].getAmount() < targetStacks[i].getMaxStackSize()) { // Same material and none full stack int move = targetStacks[i].getMaxStackSize() - targetStacks[i].getAmount(); move = Math.min(stack.getAmount(), move); targetStacks[i].setAmount(targetStacks[i].getAmount() + move); stack.setAmount(stack.getAmount() - move); } } } public List fast() { for(ItemStack stack : inputStacks) { if(stack == null || stack.getType() == Material.AIR || stack.getAmount() < 1) continue; if(filled == targetStacks.length) { toMuch.add(stack); } else { targetStacks[filled++] = stack; } } return toMuch; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Helper/OldFileUpdater.java ================================================ /* * Copyright (C) 2019 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper; import at.pcgamingfreaks.yaml.YAML; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Logger; public class OldFileUpdater { public static void updateConfig(YAML oldYAML, YAML newYAML) { int oldVersion = oldYAML.getInt("Version", -1); for(String key : newYAML.getKeys()) { String oldKey = key; if(key.equals("Version")) continue; if(oldVersion < 11) { if(key.equals("BackpackTitle") || key.equals("BackpackTitleOther")) continue; oldKey = key.replace(".SQL.", ".MySQL."); } switch(key) { case "Cooldown.Command": oldKey = "command_cooldown"; break; case "Cooldown.Sync": oldKey = "sync_cooldown"; break; case "DropOnDeath": oldKey = "drop_on_death"; break; case "MaxSize": oldKey = "max_size"; break; case "AllowedGameModes": oldKey = "allowed_game_modes"; break; case "FullInventory.CollectItems": oldKey = "full_inventory.collect_items"; break; case "FullInventory.CheckInterval": oldKey = "full_inventory.check_interval"; break; case "FullInventory.CollectRadius": oldKey = "full_inventory.collect_radius"; break; case "Misc.AutoUpdate": oldKey = "auto-update"; break; case "Misc.UseBungeeCord": oldKey = "BungeeCordMode"; break; case "Language.Language": oldKey = "Language"; break; case "Database.UseUUIDs": case "UseUUIDs": continue; } try { if(oldYAML.isSet(oldKey)) newYAML.set(key, oldYAML.getString(oldKey)); } catch(Exception e) { e.printStackTrace(); } } if(oldVersion < 11) { newYAML.set("BackpackTitleOther", oldYAML.getString("BackpackTitle", "&b{OwnerName} Backpack").replaceAll("%s", "{OwnerName}")); } } public static void updateLanguage(YAML oldYAML, YAML newYAML, Logger logger) { Map simpleConverter = new LinkedHashMap<>(), advancedConverter = new LinkedHashMap<>(); String[] keys; String helper; for(String key : oldYAML.getKeys(true)) { try { keys = key.split("\\."); if(keys.length == 3 && keys[0].equals("Language")) { switch(keys[1]) { case "Console": if("NotFromConsole".equals(keys[2])) { advancedConverter.put("Language.NotFromConsole", "&c" + oldYAML.getString(key)); } break; case "Ingame": helper = keys[0] + "." + keys[1] + "."; switch(keys[2]) { case "NoPermission": advancedConverter.put(key, "&c" + oldYAML.getString(key)); break; case "OwnBackPackClose": simpleConverter.put(helper + "OwnBackpackClose", key); break; case "PlayerBackPackClose": advancedConverter.put(helper + "PlayerBackpackClose", oldYAML.getString(key).replace("%s", "{OwnerName}")); break; case "InvalidBackpack": simpleConverter.put(key, key); break; case "BackpackCleaned": simpleConverter.put("Language.Ingame.Clean.BackpackCleaned", key); break; case "Cooldown": advancedConverter.put("Language.Ingame.Open.Cooldown", "&2" + oldYAML.getString(key)); break; case "WrongGameMode": simpleConverter.put("Language.Ingame.Open.WrongGameMode", key); break; } break; case "Description": helper = "Language.Commands.Description."; simpleConverter.put(helper + keys[2], key); break; } } if(keys.length == 1) { switch(keys[0]) { case "LanguageName": case "Author": simpleConverter.put(key, key); } } } catch(Exception e) { logger.warning("Failed to convert the old \"" + key + "\" language value into the corresponding new one."); e.printStackTrace(); } } // Patch them into the lang file try { for(Map.Entry entry : advancedConverter.entrySet()) { newYAML.set(entry.getKey(), entry.getValue()); } for(Map.Entry entry : simpleConverter.entrySet()) { newYAML.set(entry.getKey(), oldYAML.getString(entry.getValue())); } } catch(Exception e) { logger.warning("Failed to write the old language values into the new language file."); e.printStackTrace(); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/InventorySerializer.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Bukkit.ItemStackSerializer.ItemStackSerializer; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.ConsoleColor; import lombok.Getter; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import java.util.logging.Level; import java.util.logging.Logger; public class InventorySerializer { @SuppressWarnings("deprecation") private static final ItemStackSerializer BUKKIT_ITEM_STACK_SERIALIZER = ItemStackSerializer.makeBukkitItemStackSerializer(); private final Logger logger; private final ItemStackSerializer serializer; @Getter private final int usedSerializer; public InventorySerializer(Logger logger) { this.logger = logger; ItemStackSerializer serializer = null; int usedSerializer = 2; try { if(ItemStackSerializer.isNBTItemStackSerializerAvailable()) { serializer = ItemStackSerializer.makeNBTItemStackSerializer(logger); } } catch(Exception e) { logger.log(Level.SEVERE, "Failed to produce serializer!", e); } if(serializer == null) { logger.severe("NBTItemStackSerializer does not support your Minecraft version!\nFalling back to BukkitItemStackSerializer! This most likely is wrong!"); if (MCVersion.isOlderThan(MCVersion.MC_NMS_1_8_R1)) { usedSerializer = 0; serializer = BUKKIT_ITEM_STACK_SERIALIZER; } } this.serializer = serializer; this.usedSerializer = usedSerializer; } public byte[] serialize(Inventory inv) { return serializer.serialize(inv.getContents()); } public ItemStack[] deserialize(byte[] data, int usedSerializer) { if(data == null) return null; switch(usedSerializer) { case 0: return BUKKIT_ITEM_STACK_SERIALIZER.deserialize(data); case 1: if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_13)) logger.warning(ConsoleColor.YELLOW + "Backpack was created with an old version of minepacks and minecraft. There is the chance that some items will disappear from it." + ConsoleColor.RESET); case 2: return serializer.deserialize(data); default: logger.warning(ConsoleColor.RED + "No compatible deserializer for backpack format available!" + ConsoleColor.RESET); } return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Language.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Config.YamlFileManager; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Helper.OldFileUpdater; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.MagicValues; import at.pcgamingfreaks.Version; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; public class Language extends at.pcgamingfreaks.Bukkit.Config.Language { private static final Version LANG_VERSION = new Version(MagicValues.LANG_VERSION); public Language(Minepacks plugin) { super(plugin, LANG_VERSION); } @Override protected void doUpgrade(@NotNull YamlFileManager oldLang) { if(oldLang.getVersion().olderThan(new Version(10))) // Pre v2.0 versions { OldFileUpdater.updateLanguage(oldLang.getYamlE(), getYaml(), getLogger()); } else { super.doUpgrade(oldLang); } } public String[] getCommandAliases(final String command) { return getCommandAliases(command, new String[0]); } public String[] getCommandAliases(final String command, final @NotNull String... defaults) { List aliases = getLangE().getStringList("Command." + command, new ArrayList<>(0)); return (aliases.size() > 0) ? aliases.toArray(new String[0]) : defaults; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/FilesToSQLMigration.java ================================================ /* * Copyright (C) 2018 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Files; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileInputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class FilesToSQLMigration extends ToSQLMigration { private final @Language("SQL") String queryInsertUsers, queryInsertBackpacks; private final File saveFolder; protected FilesToSQLMigration(@NotNull Minepacks plugin, @NotNull Files oldDb, @NotNull String dbType, boolean global) throws Exception { super(plugin, oldDb, dbType, global); saveFolder = new File(this.plugin.getDataFolder(), Files.FOLDER_NAME); queryInsertUsers = replacePlaceholders(newDb, "INSERT INTO {TablePlayers} ({FieldUUID},{FieldName}) VALUES (?,?);"); queryInsertBackpacks = replacePlaceholders(newDb, "INSERT INTO {TableBackpacks} ({FieldBPOwner},{FieldBPITS},{FieldBPVersion}) VALUES (?,?,?);"); } @Override public @Nullable MigrationResult migrate() throws Exception { File[] allFiles = saveFolder.listFiles((dir, name) -> name.endsWith(Files.EXT)); if(allFiles == null) return null; try(Connection connection = newDb.getConnection(); PreparedStatement statementInsertUser = connection.prepareStatement(queryInsertUsers, PreparedStatement.RETURN_GENERATED_KEYS); PreparedStatement statementInsertBackpack = connection.prepareStatement(queryInsertBackpacks)) { int migrated = 0; for(File file : allFiles) { String name = file.getName().substring(0, file.getName().length() - Files.EXT.length()); statementInsertUser.setString(1, name); statementInsertUser.setString(2, "UNKNOWN"); statementInsertUser.executeUpdate(); try(ResultSet rs = statementInsertUser.getGeneratedKeys()) { if(rs.next()) { try(FileInputStream fis = new FileInputStream(file)) { int version = fis.read(); byte[] data = new byte[(int) (file.length() - 1)]; int readCount = fis.read(data); if(file.length() - 1 != readCount) plugin.getLogger().warning("Problem reading file, read " + readCount + " of " + (file.length() - 1) + " bytes."); statementInsertBackpack.setInt(1, rs.getInt(1)); statementInsertBackpack.setBytes(2, data); statementInsertBackpack.setInt(3, version); statementInsertBackpack.executeUpdate(); migrated++; } } } } return new MigrationResult("Migrated " + migrated + " backpacks from Files to " + newDb.getClass().getSimpleName(), MigrationResult.MigrationResultType.SUCCESS); } finally { newDb.close(); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/Migration.java ================================================ /* * Copyright (C) 2018 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class Migration { protected final Minepacks plugin; protected final Database oldDb; protected Migration(@NotNull Minepacks plugin, @NotNull Database oldDb) { this.plugin = plugin; this.oldDb = oldDb; } public abstract @Nullable MigrationResult migrate() throws Exception; } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/MigrationCallback.java ================================================ /* * Copyright (C) 2018 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; public interface MigrationCallback { void onResult(MigrationResult result); } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/MigrationManager.java ================================================ /* * Copyright (C) 2019 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.ConsoleColor; import at.pcgamingfreaks.Minepacks.Bukkit.Database.*; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Reflection; import org.bukkit.event.HandlerList; import java.util.Locale; public class MigrationManager { private final Minepacks plugin; public MigrationManager(final Minepacks plugin) { this.plugin = plugin; } public void migrateDB(final String targetDatabaseType, final MigrationCallback callback) { final Migration migration = getMigrationPerformer(targetDatabaseType); if(migration == null) { callback.onResult(new MigrationResult("There is no need to migrate the database.", MigrationResult.MigrationResultType.NOT_NEEDED)); return; } final Database db = plugin.getDatabase(); //region Disable the plugin except for the database try { plugin.getLogger().info("Unloading plugin for migration"); Reflection.setValue(plugin, "database", null); // Hack to prevent the unload of the database //noinspection ConstantConditions Reflection.getMethod(Minepacks.class, "unload").invoke(plugin); // Unload plugin HandlerList.unregisterAll(db); // Disable events for database Reflection.setValue(plugin, "database", db); } catch(Exception e) { plugin.getLogger().warning(ConsoleColor.RED + "Failed to unload plugin! Please restart your server!" + ConsoleColor.RESET); e.printStackTrace(); callback.onResult(new MigrationResult("Failed to unload plugin! Please restart your server!", MigrationResult.MigrationResultType.ERROR)); return; } //endregion //region Migrate data Minepacks.getScheduler().runAsync(task -> { MigrationResult migrationResult = null; try { plugin.getLogger().info("Start migrating data to new database"); migrationResult = migration.migrate(); plugin.getConfiguration().setDatabaseType(targetDatabaseType); } catch(Exception e) { e.printStackTrace(); plugin.getLogger().warning(ConsoleColor.RED + "There was a problem migrating from " + db.getClass().getName() + " to " + targetDatabaseType + ConsoleColor.RESET); callback.onResult(new MigrationResult("There was a problem migrating from " + db.getClass().getName() + " to " + targetDatabaseType + ". Please check the console for details.", MigrationResult.MigrationResultType.ERROR)); } //region Start the plugin again final MigrationResult migrationResultFinal = migrationResult; Minepacks.getScheduler().runNextTick(task1 -> { db.close(); // No need to reload the config try { plugin.getLogger().info("Migration is done, loading the plugin again."); //noinspection ConstantConditions Reflection.getMethod(Minepacks.class, "load").invoke(plugin); // load the plugin again plugin.getLogger().info(ConsoleColor.GREEN + "Plugin loaded successful and is ready to use again." + ConsoleColor.RESET); if(migrationResultFinal != null) callback.onResult(migrationResultFinal); } catch(Exception e) { plugin.getLogger().warning(ConsoleColor.RED + "Failed to start plugin again!" + ConsoleColor.RESET); e.printStackTrace(); } }); //endregion }); //endregion } public Migration getMigrationPerformer(String targetDatabaseType) { try { boolean global = false; if(targetDatabaseType.toLowerCase(Locale.ROOT).equals("external") || targetDatabaseType.toLowerCase(Locale.ROOT).equals("global") || targetDatabaseType.toLowerCase(Locale.ROOT).equals("shared")) { /*if[STANDALONE] plugin.getLogger().warning(ConsoleColor.RED + "The shared database connection option is not available in standalone mode!" + ConsoleColor.RESET); return null; else[STANDALONE]*/ at.pcgamingfreaks.PluginLib.Database.DatabaseConnectionPool pool = at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getDatabaseConnectionPool(); if(pool == null) { plugin.getLogger().warning(ConsoleColor.RED + "The shared connection pool is not initialized correctly!" + ConsoleColor.RESET); return null; } targetDatabaseType = pool.getDatabaseType().toLowerCase(Locale.ROOT); global = true; /*end[STANDALONE]*/ } switch(targetDatabaseType.toLowerCase(Locale.ROOT)) { case "flat": case "file": case "files": if(!(plugin.getDatabase() instanceof SQL)) return null; return new SQLtoFilesMigration(plugin, (SQL) plugin.getDatabase()); case "mysql": if(plugin.getDatabase() instanceof MySQL) return null; if(plugin.getDatabase() instanceof SQL) return new SQLtoSQLMigration(plugin, (SQL) plugin.getDatabase(), "mysql", global); else return new FilesToSQLMigration(plugin, (Files) plugin.getDatabase(), "mysql", global); case "sqlite": if(plugin.getDatabase() instanceof SQLite) return null; if(plugin.getDatabase() instanceof SQL) return new SQLtoSQLMigration(plugin, (SQL) plugin.getDatabase(), "sqlite", global); else return new FilesToSQLMigration(plugin, (Files) plugin.getDatabase(), "sqlite", global); default: plugin.getLogger().warning(String.format(Database.MESSAGE_UNKNOWN_DB_TYPE, plugin.getConfiguration().getDatabaseType())); return null; } } catch(Exception e) { e.printStackTrace(); } return null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/MigrationResult.java ================================================ /* * Copyright (C) 2018 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import org.jetbrains.annotations.NotNull; public class MigrationResult { public enum MigrationResultType { SUCCESS, ERROR, NOT_NEEDED } private final String message; private final MigrationResultType type; public MigrationResult(@NotNull String message, @NotNull MigrationResultType type) { this.message = message; this.type = type; } public @NotNull MigrationResultType getType() { return type; } public @NotNull String getMessage() { return message; } @Override public String toString() { return getType().name() + ": " + getMessage(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/SQLtoFilesMigration.java ================================================ /* * Copyright (C) 2018 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Files; import at.pcgamingfreaks.Minepacks.Bukkit.Database.SQL; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Reflection; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; public class SQLtoFilesMigration extends Migration { private final String sqlQuery; private final File saveFolder; protected SQLtoFilesMigration(@NotNull Minepacks plugin, @NotNull SQL oldDb) throws InvocationTargetException, IllegalAccessException { super(plugin, oldDb); @Language("SQL") String query = "SELECT {FieldUUID},{FieldBPITS},{FieldBPVersion} FROM {TablePlayers} INNER JOIN {TableBackpacks} ON {FieldPlayerID}={FieldBPOwner};"; //noinspection ConstantConditions sqlQuery = (String) Reflection.getMethod(SQL.class, "replacePlaceholders", String.class).invoke(oldDb, query); saveFolder = new File(this.plugin.getDataFolder(), Files.FOLDER_NAME); if(!saveFolder.exists() && !saveFolder.mkdirs()) plugin.getLogger().warning("Failed to create save folder (" + saveFolder.getAbsolutePath() + ")."); } @Override public @Nullable MigrationResult migrate() throws Exception { int migrated = 0; try(Connection connection = ((SQL) oldDb).getConnection(); Statement st = connection.createStatement(); ResultSet rs = st.executeQuery(sqlQuery)) { while(rs.next()) { try(FileOutputStream fos = new FileOutputStream(new File(saveFolder, rs.getString(1) + Files.EXT))) { fos.write(rs.getInt(3)); fos.write(rs.getBytes(2)); } migrated++; } } return new MigrationResult("Migrated " + migrated + " backpacks from " + oldDb.getClass().getSimpleName() + " to Files.", MigrationResult.MigrationResultType.SUCCESS); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/SQLtoSQLMigration.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.Minepacks.Bukkit.Database.SQL; import at.pcgamingfreaks.Minepacks.Bukkit.Database.SQLite; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.sql.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @SuppressWarnings("ConstantConditions") public class SQLtoSQLMigration extends ToSQLMigration { private final @Language("SQL") String queryInsertUsers, queryInsertBackpacks; protected SQLtoSQLMigration(@NotNull Minepacks plugin, @NotNull SQL oldDb, @NotNull String dbType, boolean global) throws Exception { super(plugin, oldDb, dbType, global); queryInsertUsers = replacePlaceholders(newDb, "INSERT INTO {TablePlayers} ({FieldPlayerID},{FieldName},{FieldUUID}) VALUES (?,?,?);"); queryInsertBackpacks = replacePlaceholders(newDb, "INSERT INTO {TableBackpacks} ({FieldBPOwner},{FieldBPITS},{FieldBPVersion},{FieldBPLastUpdate}) VALUES (?,?,?,?);"); } @Override public @Nullable MigrationResult migrate() throws Exception { try(Connection readConnection = ((SQL) oldDb).getConnection(); Connection writeConnection = newDb.getConnection(); Statement readStatement = readConnection.createStatement()) { int users = migrate("users", writeConnection, readStatement, "SELECT * FROM {TablePlayers};", queryInsertUsers); int backpacks = migrate("backpacks", writeConnection, readStatement, "SELECT * FROM {TableBackpacks};", queryInsertBackpacks); return new MigrationResult("Migrated " + users + " users and " + backpacks + " backpacks from " + oldDb.getClass().getSimpleName() + " to " + newDb.getClass().getSimpleName() + ".", MigrationResult.MigrationResultType.SUCCESS); } finally { newDb.close(); } } private int migrate(@NotNull String type, @NotNull Connection writeConnection, @NotNull Statement readStatement, @Language("SQL") String readQuery, @Language("SQL") String insertQuery) throws Exception { int count = 0; byte mode = (byte) ((type.equals("users")) ? 0 : 1); plugin.getLogger().info("Migrate " + type + " ..."); try(ResultSet resultSet = readStatement.executeQuery(replacePlaceholders((SQL) oldDb, readQuery)); PreparedStatement preparedStatement = writeConnection.prepareStatement(replacePlaceholders(newDb, insertQuery))) { while(resultSet.next()) { switch(mode) { case 0: migrateUser(resultSet, preparedStatement); break; case 1: migrateBackpack(resultSet, preparedStatement); break; } preparedStatement.addBatch(); count++; } preparedStatement.executeBatch(); } plugin.getLogger().info("Migrated " + count + " " + type + "."); return count; } private void migrateUser(@NotNull ResultSet usersResultSet, @NotNull PreparedStatement preparedStatement) throws Exception { int userId = usersResultSet.getInt((String) FIELD_PLAYER_ID.get(oldDb)); preparedStatement.setInt(1, userId); preparedStatement.setString(2, usersResultSet.getString((String) FIELD_PLAYER_NAME.get(oldDb))); preparedStatement.setString(3, usersResultSet.getString((String) FIELD_PLAYER_UUID.get(oldDb))); } private void migrateBackpack(@NotNull ResultSet backpacksResultSet, @NotNull PreparedStatement preparedStatement) throws Exception { preparedStatement.setInt(1, backpacksResultSet.getInt((String) FIELD_BP_OWNER.get(oldDb))); preparedStatement.setBytes(2, backpacksResultSet.getBytes((String) FIELD_BP_ITS.get(oldDb))); preparedStatement.setInt(3, backpacksResultSet.getInt((String) FIELD_BP_VERSION.get(oldDb))); final DateFormat sqliteDateFormat = new SimpleDateFormat("yyyy-MM-dd"); if(oldDb instanceof SQLite) { preparedStatement.setTimestamp(4, new Timestamp(sqliteDateFormat.parse(backpacksResultSet.getString((String) FIELD_BP_LAST_UPDATE.get(oldDb))).getTime())); } else { preparedStatement.setString(4, sqliteDateFormat.format(new Date(backpacksResultSet.getTimestamp((String) FIELD_BP_LAST_UPDATE.get(oldDb)).getTime()))); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Migration/ToSQLMigration.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.Migration; import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Database.MySQL; import at.pcgamingfreaks.Minepacks.Bukkit.Database.SQL; import at.pcgamingfreaks.Minepacks.Bukkit.Database.SQLite; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Reflection; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; @SuppressWarnings("ConstantConditions") public abstract class ToSQLMigration extends Migration { protected static final Method METHOD_REPLACE_PLACEHOLDERS = Reflection.getMethod(SQL.class, "replacePlaceholders", String.class); protected static final Field FIELD_PLAYER_ID = Reflection.getField(SQL.class, "fieldPlayerID"); protected static final Field FIELD_PLAYER_UUID = Reflection.getField(SQL.class, "fieldPlayerUUID"); protected static final Field FIELD_PLAYER_NAME = Reflection.getField(SQL.class, "fieldPlayerName"); protected static final Field FIELD_BP_OWNER = Reflection.getField(SQL.class, "fieldBpOwner"); protected static final Field FIELD_BP_ITS = Reflection.getField(SQL.class, "fieldBpIts"); protected static final Field FIELD_BP_VERSION = Reflection.getField(SQL.class, "fieldBpVersion"); protected static final Field FIELD_BP_LAST_UPDATE = Reflection.getField(SQL.class, "fieldBpLastUpdate"); protected final SQL newDb; protected ToSQLMigration(@NotNull Minepacks plugin, @NotNull Database oldDb, @NotNull String dbType, boolean global) { super(plugin, oldDb); /*if[STANDALONE] ConnectionProvider connectionProvider = null; else[STANDALONE]*/ ConnectionProvider connectionProvider = (global) ? at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getDatabaseConnectionPool().getConnectionProvider() : null; /*end[STANDALONE]*/ switch(dbType) { case "mysql": newDb = new MySQL(plugin, connectionProvider); break; case "sqlite": final File dbFile = new File(SQLite.getDbFile(plugin)); if(dbFile.exists() && !dbFile.renameTo(new File(SQLite.getDbFile(plugin) + ".old_" + System.currentTimeMillis()))) { plugin.getLogger().warning("Failed to rename old database file."); } newDb = new SQLite(plugin, connectionProvider); break; default: newDb = null; } } protected @Language("SQL") String replacePlaceholders(SQL database, @Language("SQL") String query) throws Exception { return (String) METHOD_REPLACE_PLACEHOLDERS.invoke(database, query); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/MySQL.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider; import at.pcgamingfreaks.Database.ConnectionProvider.MySQLConnectionProvider; import at.pcgamingfreaks.Database.DBTools; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.sql.Connection; import java.sql.SQLException; public class MySQL extends SQL { public MySQL(@NotNull Minepacks plugin, @Nullable ConnectionProvider connectionProvider) { super(plugin, (connectionProvider == null) ? new MySQLConnectionProvider(plugin.getLogger(), plugin.getDescription().getName(), plugin.getConfiguration()) : connectionProvider); } @Override protected void updateQueriesForDialect() { queryDeleteOldBackpacks = "DELETE FROM {TableBackpacks} WHERE {FieldBPLastUpdate} + INTERVAL {VarMaxAge} day < NOW()"; queryUpdateBp = queryUpdateBp.replace("{NOW}", "NOW()"); } @Override protected void checkDB() { try(Connection connection = getConnection()) { DBTools.updateDB(connection, replacePlaceholders("CREATE TABLE IF NOT EXISTS {TablePlayers} (\n{FieldPlayerID} INT UNSIGNED NOT NULL AUTO_INCREMENT,\n{FieldName} VARCHAR(16) NOT NULL,\n" + "{FieldUUID} CHAR(" + ((useUUIDSeparators) ? "36" : "32") + ") DEFAULT NULL," + "\nPRIMARY KEY ({FieldPlayerID}),\n" + "UNIQUE INDEX {FieldUUID}_UNIQUE ({FieldUUID})\n);")); DBTools.updateDB(connection, replacePlaceholders("CREATE TABLE IF NOT EXISTS {TableBackpacks} (\n{FieldBPOwner} INT UNSIGNED NOT NULL,\n{FieldBPITS} MEDIUMBLOB,\n{FieldBPVersion} INT DEFAULT 0,\n" + "{FieldBPLastUpdate} TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n" + "PRIMARY KEY ({FieldBPOwner}),\nCONSTRAINT fk_{TableBackpacks}_{TablePlayers}_{FieldBPOwner} FOREIGN KEY ({FieldBPOwner}) " + "REFERENCES {TablePlayers} ({FieldPlayerID}) ON DELETE CASCADE ON UPDATE CASCADE\n);")); if(syncCooldown) { DBTools.updateDB(connection, replacePlaceholders("CREATE TABLE IF NOT EXISTS {TableCooldowns} (\n{FieldCDPlayer} INT UNSIGNED NOT NULL,\n{FieldCDTime} DATETIME NOT NULL,\nPRIMARY KEY ({FieldCDPlayer}),\n" + "CONSTRAINT fk_{TableCooldowns}_{TablePlayers}_{FieldCDPlayer} FOREIGN KEY ({FieldCDPlayer}) " + "REFERENCES {TablePlayers} ({FieldPlayerID}) ON DELETE CASCADE ON UPDATE CASCADE\n);")); } } catch (SQLException e) { e.printStackTrace(); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/SQL.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider; import at.pcgamingfreaks.Database.DBTools; import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Utils; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import java.sql.*; import java.util.logging.Level; public abstract class SQL extends Database { private final ConnectionProvider dataSource; protected String tablePlayers, tableBackpacks, tableCooldowns; // Table Names protected String fieldPlayerName, fieldPlayerID, fieldPlayerUUID, fieldBpOwner, fieldBpIts, fieldBpVersion, fieldBpLastUpdate, fieldCdPlayer, fieldCdTime; // Table Fields @Language("SQL") protected String queryUpdatePlayerAdd, queryGetPlayerID, queryInsertBp, queryUpdateBp, queryGetBP, queryDeleteOldBackpacks; // DB Queries @Language("SQL") protected String queryDeleteOldCooldowns, querySyncCooldown, queryGetCooldown; // DB Queries protected boolean syncCooldown; public SQL(@NotNull Minepacks plugin, @NotNull ConnectionProvider connectionProvider) { super(plugin); dataSource = connectionProvider; if(!dataSource.isAvailable()) throw new IllegalStateException("Failed to initialize database connection!"); loadSettings(); buildQueries(); checkDB(); checkUUIDs(); // Check if there are user accounts without UUID // Delete old backpacks if(maxAge > 0) { try(Connection connection = getConnection(); Statement statement = connection.createStatement()) { statement.execute(queryDeleteOldBackpacks); } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to delete old backpacks! Error: {0}", e.getMessage()); } } // Delete old cooldowns if(syncCooldown) { try(Connection connection = getConnection()) { DBTools.runStatement(connection, queryDeleteOldCooldowns, new Timestamp(System.currentTimeMillis())); } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to delete cooldowns! Error: {0}", e.getMessage()); } } } protected void loadSettings() { // Load table and field names tablePlayers = plugin.getConfiguration().getUserTable(); tableBackpacks = plugin.getConfiguration().getBackpackTable(); tableCooldowns = plugin.getConfiguration().getCooldownTable(); fieldPlayerID = plugin.getConfiguration().getDBFields("User.Player_ID", "id"); fieldPlayerName = plugin.getConfiguration().getDBFields("User.Name", "name"); fieldPlayerUUID = plugin.getConfiguration().getDBFields("User.UUID", "uuid"); fieldBpOwner = plugin.getConfiguration().getDBFields("Backpack.Owner_ID", "owner"); fieldBpIts = plugin.getConfiguration().getDBFields("Backpack.ItemStacks", "its"); fieldBpVersion = plugin.getConfiguration().getDBFields("Backpack.Version", "version"); fieldBpLastUpdate = plugin.getConfiguration().getDBFields("Backpack.LastUpdate", "lastUpdate"); fieldCdPlayer = plugin.getConfiguration().getDBFields("Cooldown.Player_ID", "id"); fieldCdTime = plugin.getConfiguration().getDBFields("Cooldown.Time", "time"); syncCooldown = plugin.getConfiguration().isCommandCooldownSyncEnabled(); } @Override public void close() { super.close(); Utils.blockThread(1); // Give the database some time to perform async operations dataSource.close(); } protected void checkUUIDs() { try(Connection connection = getConnection()) { DBTools.validateUUIDs(plugin.getLogger(), connection, tablePlayers, fieldPlayerName, fieldPlayerUUID, fieldPlayerID, useUUIDSeparators, onlineUUIDs); } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to check UUIDs! Error: {0}", e.getMessage()); } } public Connection getConnection() throws SQLException { return dataSource.getConnection(); } protected abstract void checkDB(); protected final void buildQueries() { // Build the SQL queries with placeholders for the table and field names queryGetBP = "SELECT {FieldBPOwner},{FieldBPITS},{FieldBPVersion} FROM {TableBackpacks} INNER JOIN {TablePlayers} ON {TableBackpacks}.{FieldBPOwner}={TablePlayers}.{FieldPlayerID} WHERE {FieldUUID}=?;"; querySyncCooldown = "INSERT INTO {TableCooldowns} ({FieldCDPlayer},{FieldCDTime}) SELECT {FieldPlayerID},? FROM {TablePlayers} WHERE {FieldUUID}=? ON DUPLICATE KEY UPDATE {FieldCDTime}=?;"; queryUpdatePlayerAdd = "INSERT INTO {TablePlayers} ({FieldName},{FieldUUID}) VALUES (?,?) ON DUPLICATE KEY UPDATE {FieldName}=?;"; queryGetPlayerID = "SELECT {FieldPlayerID} FROM {TablePlayers} WHERE {FieldUUID}=?;"; queryGetCooldown = "SELECT * FROM {TableCooldowns} WHERE {FieldCDPlayer} IN (SELECT {FieldPlayerID} FROM {TablePlayers} WHERE {FieldUUID}=?);"; queryInsertBp = "REPLACE INTO {TableBackpacks} ({FieldBPOwner},{FieldBPITS},{FieldBPVersion}) VALUES (?,?,?);"; queryUpdateBp = "UPDATE {TableBackpacks} SET {FieldBPITS}=?,{FieldBPVersion}=?,{FieldBPLastUpdate}={NOW} WHERE {FieldBPOwner}=?;"; queryDeleteOldBackpacks = "DELETE FROM {TableBackpacks} WHERE {FieldBPLastUpdate} < DATE('now', '-{VarMaxAge} days')"; queryDeleteOldCooldowns = "DELETE FROM {TableCooldowns} WHERE {FieldCDTime} runStatement(query, args)); } protected void runStatement(final String query, final Object... args) { try(Connection connection = getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(query)) { for(int i = 0; args != null && i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } preparedStatement.execute(); } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, e, () -> "Query: " + query); } } // Plugin Functions @Override public void updatePlayer(final Player player) { runStatementAsync(queryUpdatePlayerAdd, player.getName(), getPlayerFormattedUUID(player), player.getName()); } @Override public void saveBackpack(final Backpack backpack) { final byte[] data = itsSerializer.serialize(backpack.getInventory()); final int id = backpack.getOwnerDatabaseId(), usedSerializer = itsSerializer.getUsedSerializer(); final String nameOrUUID = getPlayerFormattedUUID(backpack.getOwnerId()), name = backpack.getOwner().getName(); Runnable runnable = () -> { try(Connection connection = getConnection()) { if(id <= 0) { try(PreparedStatement ps = connection.prepareStatement(queryGetPlayerID)) { ps.setString(1, nameOrUUID); try(ResultSet rs = ps.executeQuery()) { if(rs.next()) { final int newID = rs.getInt(fieldPlayerID); DBTools.runStatement(connection, queryInsertBp, newID, data, usedSerializer); Minepacks.getScheduler().runNextTick(task -> backpack.setOwnerDatabaseId(newID)); } else { plugin.getLogger().warning("Failed saving backpack for: " + name + " (Unable to get players ID from database)"); writeBackup(name, nameOrUUID, usedSerializer, data); } } } } else { DBTools.runStatement(connection, queryUpdateBp, data, usedSerializer, id); } } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to save backpack in database! Error: {0}", e.getMessage()); writeBackup(name, nameOrUUID, usedSerializer, data); } }; if(asyncSave) Minepacks.getScheduler().runAsync(task -> runnable.run()); else runnable.run(); } @Override protected void loadBackpack(final OfflinePlayer player, final Callback callback) { Minepacks.getScheduler().runAsync(task -> { try(Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(queryGetBP)) { final String playerUUID = getPlayerFormattedUUID(player); ps.setString(1, playerUUID); final int bpID, version; final byte[] data; try(ResultSet rs = ps.executeQuery()) { if(rs.next()) { bpID = rs.getInt(fieldBpOwner); version = rs.getInt(fieldBpVersion); data = rs.getBytes(fieldBpIts); } else { bpID = -1; version = 0; data = null; } } ItemStack[] its = itsSerializer.deserialize(data, version); if (data != null && data.length != 0 && its == null) { writeBackup(player.getName(), playerUUID, version, data); } final Backpack backpack = (its != null) ? new Backpack(player, its, bpID) : null; Minepacks.getScheduler().runNextTick(task1 -> { if(backpack != null) { callback.onResult(backpack); } else { callback.onFail(); } }); } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to load backpack! Error: {0}", e.getMessage()); Minepacks.getScheduler().runNextTick(task1 -> callback.onFail()); } }); } @Override public void syncCooldown(Player player, long cooldownTime) { Timestamp ts = new Timestamp(cooldownTime); runStatementAsync(querySyncCooldown, ts, getPlayerFormattedUUID(player), ts); } @Override public void getCooldown(final Player player, final Callback callback) { Minepacks.getScheduler().runAsync(asyncTask -> { try(Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(queryGetCooldown)) { ps.setString(1, getPlayerFormattedUUID(player)); try(ResultSet rs = ps.executeQuery()) { final long time = (rs.next()) ? rs.getTimestamp(fieldCdTime).getTime() : 0; Minepacks.getScheduler().runNextTick(task -> callback.onResult(time)); } } catch(SQLException e) { plugin.getLogger().log(Level.SEVERE, "Failed to load cooldown! Error: {0}", e.getMessage()); Minepacks.getScheduler().runNextTick(task -> callback.onResult(0L)); } }); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/SQLite.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database; import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider; import at.pcgamingfreaks.Database.ConnectionProvider.SQLiteConnectionProvider; import at.pcgamingfreaks.Database.DBTools; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Version; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class SQLite extends SQL { public static String getDbFile(final @NotNull Minepacks plugin) { return plugin.getDataFolder().getAbsolutePath() + File.separator + "backpack.db"; } //TODO add cooldown sync table public SQLite(final @NotNull Minepacks plugin, final @Nullable ConnectionProvider connectionProvider) { super(plugin, (connectionProvider == null) ? new SQLiteConnectionProvider(plugin.getLogger(), plugin.getDescription().getName(), getDbFile(plugin)) : connectionProvider); } @Override protected void loadSettings() { // Set table and field names to fixed values to prevent users from destroying old databases. fieldPlayerID = "player_id"; fieldPlayerName = "name"; fieldPlayerUUID = "uuid"; fieldBpOwner = "owner"; //noinspection SpellCheckingInspection fieldBpIts = "itemstacks"; fieldBpVersion = "version"; fieldBpLastUpdate = "lastupdate"; tablePlayers = "backpack_players"; tableBackpacks = "backpacks"; tableCooldowns = "backpack_cooldowns"; fieldCdPlayer = "player_id"; fieldCdTime = "time"; // Set fixed settings useUUIDSeparators = false; syncCooldown = false; } @Override protected void updateQueriesForDialect() { queryInsertBp = queryInsertBp.replaceAll("\\) VALUES \\(\\?,\\?,\\?", ",{FieldBPLastUpdate}) VALUES (?,?,?,DATE('now')"); queryDeleteOldBackpacks = "DELETE FROM {TableBackpacks} WHERE {FieldBPLastUpdate} < DATE('now', '-{VarMaxAge} days')"; queryUpdateBp = queryUpdateBp.replaceAll("\\{NOW}", "DATE('now')"); queryUpdatePlayerAdd = "INSERT OR IGNORE INTO {TablePlayers} ({FieldName},{FieldUUID}) VALUES (?,?);"; } @SuppressWarnings("SqlResolve") @Override protected void checkDB() { try(Connection connection = getConnection(); Statement stmt = connection.createStatement()) { Version dbVersion = getDatabaseVersion(stmt); stmt.execute("CREATE TABLE IF NOT EXISTS `backpack_players` (`player_id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` CHAR(16) NOT NULL , `uuid` CHAR(32) UNIQUE);"); try { stmt.execute("ALTER TABLE `backpack_players` ADD COLUMN `uuid` CHAR(32);"); } catch(SQLException ignored) {} stmt.execute("CREATE TABLE IF NOT EXISTS `backpacks` (`owner` INT UNSIGNED PRIMARY KEY, `itemstacks` BLOB, `version` INT DEFAULT 0, `lastupdate` DATE);"); try { stmt.execute("ALTER TABLE `backpacks` ADD COLUMN `version` INT DEFAULT 0;"); } catch(SQLException ignored) {} try { stmt.execute("ALTER TABLE `backpacks` ADD COLUMN `lastupdate` DATE DEFAULT '2020-09-24';"); } catch(SQLException ignored) {} DBTools.runStatement(connection, "INSERT OR REPLACE INTO `minepacks_metadata` (`key`, `value`) VALUES ('db_version',?);", plugin.getDescription().getVersion()); } catch(SQLException e) { e.printStackTrace(); } } private @NotNull Version getDatabaseVersion(final @NotNull Statement stmt) throws SQLException { stmt.execute("CREATE TABLE IF NOT EXISTS `minepacks_metadata` (`key` CHAR(32) PRIMARY KEY NOT NULL, `value` TEXT);"); try(ResultSet rs = stmt.executeQuery("SELECT `value` FROM `minepacks_metadata` WHERE `key`='db_version';")) { if(rs.next()) return new Version(rs.getString("value")); } return new Version("0"); } @Override public void updatePlayer(final Player player) { Minepacks.getScheduler().runAsync(task -> { runStatement(queryUpdatePlayerAdd, player.getName(), getPlayerFormattedUUID(player)); runStatement("UPDATE `" + tablePlayers + "` SET `" + fieldPlayerName + "`=? WHERE `" + fieldPlayerUUID + "`=?;", player.getName(), getPlayerFormattedUUID(player)); }); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/UnCacheStrategies/Interval.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgf.libs.com.tcoded.folialib.wrapper.task.WrappedTask; public class Interval extends UnCacheStrategy implements Runnable { private final WrappedTask task; public Interval(Database cache) { super(cache); task = Minepacks.getScheduler().runTimer(this, Minepacks.getInstance().getConfiguration().getUnCacheDelay(), Minepacks.getInstance().getConfiguration().getUnCacheInterval()); } @Override public void run() { for(Backpack backpack : cache.getLoadedBackpacks()) { if(backpack.getOwnerPlayer() == null && !backpack.isOpen()) { this.cache.unloadBackpack(backpack); } } } @Override public void close() { Minepacks.getScheduler().cancelTask(task); super.close(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/UnCacheStrategies/IntervalChecked.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgf.libs.com.tcoded.folialib.wrapper.task.WrappedTask; import org.bukkit.OfflinePlayer; public class IntervalChecked extends UnCacheStrategy implements Runnable { private final long delay; private final WrappedTask task; public IntervalChecked(Database cache) { super(cache); long delayTicks = Minepacks.getInstance().getConfiguration().getUnCacheDelay(); task = Minepacks.getScheduler().runTimer(this, delayTicks, Minepacks.getInstance().getConfiguration().getUnCacheInterval()); this.delay = delayTicks * 50L; } @Override public void run() { long currentTime = System.currentTimeMillis() - delay; for(Backpack backpack : cache.getLoadedBackpacks()) { OfflinePlayer owner = backpack.getOwner(); if(!owner.isOnline() && owner.getLastPlayed() < currentTime && !backpack.isOpen()) { this.cache.unloadBackpack(backpack); } } } @Override public void close() { Minepacks.getScheduler().cancelTask(task); super.close(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/UnCacheStrategies/OnDisconnect.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; public class OnDisconnect extends UnCacheStrategy implements Listener { public OnDisconnect(Database cache) { super(cache); Bukkit.getPluginManager().registerEvents(this, Minepacks.getInstance()); } @EventHandler(priority = EventPriority.MONITOR) public void playerLeaveEvent(PlayerQuitEvent event) { Backpack backpack = cache.getBackpack(event.getPlayer()); if(backpack != null && !backpack.isOpen()) { cache.unloadBackpack(backpack); } } @Override public void close() { HandlerList.unregisterAll(this); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/UnCacheStrategies/OnDisconnectDelayed.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; public class OnDisconnectDelayed extends UnCacheStrategy implements Listener { private final long delay; public OnDisconnectDelayed(Database cache) { super(cache); delay = Minepacks.getInstance().getConfiguration().getUnCacheDelay(); Bukkit.getPluginManager().registerEvents(this, Minepacks.getInstance()); } @EventHandler(priority = EventPriority.MONITOR) public void playerLeaveEvent(PlayerQuitEvent event) { final Backpack backpack = cache.getBackpack(event.getPlayer()); if(backpack != null) // We only uncache unmarried player. { Minepacks.getScheduler().runLater(() -> { if (!backpack.isOpen()) { cache.unloadBackpack(backpack); } else { Minepacks.getScheduler().runLater(() -> { if (!backpack.isOpen()) { cache.unloadBackpack(backpack); } }, delay); } }, delay); } } @Override public void close() { HandlerList.unregisterAll(this); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/UnCacheStrategies/UnCacheStrategy.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; public abstract class UnCacheStrategy { protected Database cache; protected UnCacheStrategy(Database cache) { this.cache = cache; } public static UnCacheStrategy getUnCacheStrategy(Database cache) { switch(Minepacks.getInstance().getConfiguration().getUnCacheStrategy()) { case "ondisconnect": return new OnDisconnect(cache); case "ondisconnectdelayed": return new OnDisconnectDelayed(cache); case "intervalchecked": return new IntervalChecked(cache); case "interval": default: return new Interval(cache); } } public void close() { cache = null; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/ItemsCollector.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode; import at.pcgamingfreaks.Minepacks.Bukkit.Listener.ItemFilter; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.*; public class ItemsCollector extends CancellableRunnable { private final Minepacks plugin; private final double radius; private final ItemFilter itemFilter; /** * Is the feature enabled? */ private final boolean isToggleable; /** * Default on join? */ private final boolean enabledOnJoin; /** * List of players that toggled the feature. */ private final Set toggleList; public ItemsCollector(Minepacks plugin) { this.plugin = plugin; this.radius = plugin.getConfiguration().getFullInvRadius(); this.isToggleable = plugin.getConfiguration().isFullInvToggleAllowed(); this.enabledOnJoin = plugin.getConfiguration().isFullInvEnabledOnJoin(); this.toggleList = new HashSet<>(); schedule(); itemFilter = plugin.getItemFilter(); } public boolean canUseAutoPickup(Player player) { // Check if player can use in world if(plugin.isDisabled(player) != WorldBlacklistMode.None) return false; // Check if toggle is enabled AND player has been disabled, return. if (isToggleable && !isPickupEnabled(player.getUniqueId())) return false; // Check permission return (player.hasPermission(Permissions.USE) && player.hasPermission(Permissions.FULL_PICKUP)); } @Override public void run() { for(Player player : Bukkit.getServer().getOnlinePlayers()) { Minepacks.getScheduler().runAtEntity(player, entityTask -> { if (!canUseAutoPickup(player)) return; // Inventory is full if (player.getInventory().firstEmpty() != -1) return; // Only check loaded backpacks (loading them would take too much time for a repeating task, the backpack will be loaded async soon enough) Backpack backpack = (Backpack) plugin.getBackpackCachedOnly(player); if (backpack == null) return; List entities = player.getNearbyEntities(radius, radius, radius); for(Entity entity : entities) { if(entity instanceof Item) { Item item = (Item) entity; if (!item.isDead() && item.getPickupDelay() <= 0) { Map leftover = player.getInventory().addItem(item.getItemStack()); if (!leftover.isEmpty()) { ItemStack itemStack = leftover.get(0); if (itemStack == null || itemStack.getAmount() == 0 || (itemFilter != null && itemFilter.isItemBlocked(itemStack))) { continue; } leftover = backpack.addItems(itemStack); } if (!leftover.isEmpty()) { item.setItemStack(leftover.get(0)); } else { item.remove(); } } } } }); } } @Override public void schedule() { task = getScheduler().runTimer(this::run, plugin.getConfiguration().getFullInvCheckInterval(), plugin.getConfiguration().getFullInvCheckInterval()); } public void close() { cancel(); } /** * Toggles the automatic collection for the player. * @param uuid The players UUID * @return The new state. True = collection enabled. */ public boolean toggleState(UUID uuid) { boolean removed = toggleList.remove(uuid); if (!removed) { toggleList.add(uuid); } return isPickupEnabled(uuid); } /** * The item pickup state for a certain player. * @param uuid The player uuid * @return true if enabled */ public boolean isPickupEnabled(UUID uuid) { return enabledOnJoin ^ toggleList.contains(uuid); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/BackpackEventListener.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Minepacks.Bukkit.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholders; import org.bukkit.OfflinePlayer; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerQuitEvent; public class BackpackEventListener extends MinepacksListener { private final Message messageOwnBackpackClose, messageOtherBackpackClose; private final Sound closeSound; public BackpackEventListener(Minepacks plugin) { super(plugin); messageOwnBackpackClose = plugin.getLanguage().getMessage("Ingame.OwnBackpackClose"); messageOtherBackpackClose = plugin.getLanguage().getMessage("Ingame.PlayerBackpackClose").placeholders(Placeholders.mkPlayerName("Owner")); closeSound = plugin.getConfiguration().getCloseSound(); } @EventHandler(priority = EventPriority.MONITOR) public void onClose(InventoryCloseEvent event) { if (event.getInventory() != null && event.getInventory().getHolder() instanceof Backpack && event.getPlayer() instanceof Player) { Backpack backpack = (Backpack)event.getInventory().getHolder(); Player closer = (Player)event.getPlayer(); if(backpack.canEdit(closer)) { backpack.save(); } backpack.close(closer); if(event.getPlayer().getUniqueId().equals(backpack.getOwnerId())) { messageOwnBackpackClose.send(closer); } else { messageOtherBackpackClose.send(closer, backpack.getOwner()); } if(closeSound != null) { closer.playSound(closer.getLocation(), closeSound, 1, 0); } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onClick(InventoryClickEvent event) { if (event.getInventory() != null && event.getInventory().getHolder() instanceof Backpack && event.getWhoClicked() instanceof Player) { Backpack backpack = (Backpack) event.getInventory().getHolder(); if(!backpack.canEdit((Player)event.getWhoClicked())) { event.setCancelled(true); } else { backpack.setChanged(); } } } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerLeaveEvent(PlayerQuitEvent event) { Backpack backpack = plugin.getDatabase().getBackpack(event.getPlayer()); if(backpack != null) backpack.save(); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/DisableShulkerboxes.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.Util.InventoryUtils; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.ShulkerBox; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.*; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.inventory.*; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.ItemStack; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; public class DisableShulkerboxes extends MinepacksListener { //TODO handle existing shulkerboxes in inventory protected static final Collection SHULKER_BOX_MATERIALS = new HashSet<>(); static { if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11)) { SHULKER_BOX_MATERIALS.add(Material.BLACK_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.BLUE_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.BROWN_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.CYAN_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.GREEN_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.GRAY_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.LIGHT_BLUE_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.LIME_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.MAGENTA_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.ORANGE_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.PINK_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.PURPLE_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.RED_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.WHITE_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.YELLOW_SHULKER_BOX); if(MCVersion.isOlderThan(MCVersion.MC_1_13)) { SHULKER_BOX_MATERIALS.add(Material.valueOf("SILVER_SHULKER_BOX")); } else { SHULKER_BOX_MATERIALS.add(Material.LIGHT_GRAY_SHULKER_BOX); SHULKER_BOX_MATERIALS.add(Material.SHULKER_BOX); } } } private boolean removeExisting, dropExistingContent; public DisableShulkerboxes(final Minepacks plugin) { super(plugin); removeExisting = plugin.getConfiguration().isShulkerboxesExistingDestroyEnabled(); dropExistingContent = plugin.getConfiguration().isShulkerboxesExistingDropEnabled(); } @EventHandler(ignoreCancelled = true) public void onCraft(CraftItemEvent event) { if(event.getCurrentItem() != null && SHULKER_BOX_MATERIALS.contains(event.getCurrentItem().getType())) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onInventoryClick(InventoryClickEvent event) { if(event.getCurrentItem() != null && SHULKER_BOX_MATERIALS.contains(event.getCurrentItem().getType())) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onInventoryOpen(InventoryOpenEvent event) { if(event.getInventory().getHolder() != null && event.getInventory().getHolder().getClass().getName().toLowerCase(Locale.ROOT).contains("shulker")) { if(removeExisting) { Block shulkerBlock = ((ShulkerBox) event.getInventory().getHolder()).getBlock(); if(dropExistingContent) { InventoryUtils.dropInventory(event.getInventory(), shulkerBlock.getLocation()); } event.getInventory().clear(); shulkerBlock.setType(Material.AIR); } event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemMove(InventoryMoveItemEvent event) { if(event.getItem() != null && SHULKER_BOX_MATERIALS.contains(event.getItem().getType())) { event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemMove(InventoryDragEvent event) { if(event.getCursor() != null && SHULKER_BOX_MATERIALS.contains(event.getCursor().getType())) { event.setCancelled(true); } else if(event.getOldCursor() != null && SHULKER_BOX_MATERIALS.contains(event.getOldCursor().getType())) { event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPickup(InventoryPickupItemEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getItem().getItemStack().getType())) { event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemSpawn(ItemSpawnEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getEntity().getItemStack().getType())) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getBlockPlaced().getType())) { event.getItemInHand().setType(Material.AIR); event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onBlockMultiPlace(BlockMultiPlaceEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getBlock().getType())) { event.getItemInHand().setType(Material.AIR); event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent event) { if(handleShulkerBlock(event.getBlock())) event.setCancelled(true); } @EventHandler(ignoreCancelled = true) public void onBlockDamage(BlockDamageEvent event) { if(handleShulkerBlock(event.getBlock())) event.setCancelled(true); } private boolean handleShulkerBlock(Block block) { if(SHULKER_BOX_MATERIALS.contains(block.getType())) { if(removeExisting) { ShulkerBox shulkerBox = (ShulkerBox) block.getState(); if(dropExistingContent) InventoryUtils.dropInventory(shulkerBox.getInventory(), shulkerBox.getLocation()); shulkerBox.getInventory().clear(); block.setType(Material.AIR); } return true; } return false; } @EventHandler(ignoreCancelled = true) public void onBlockIgnite(BlockIgniteEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getBlock().getType())) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onBlockCanBuild(BlockCanBuildEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getBlock().getType())) { event.setBuildable(false); } } @EventHandler(ignoreCancelled = true) public void onBlockDispense(BlockDispenseEvent event) { if(SHULKER_BOX_MATERIALS.contains(event.getBlock().getType())) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onPrepareItemCraftEvent(PrepareItemCraftEvent event) { if(event.getRecipe() == null) return; Material itemType = event.getRecipe().getResult().getType(); if(itemType == Material.SHULKER_SHELL || SHULKER_BOX_MATERIALS.contains(itemType)) { event.getInventory().setResult(new ItemStack(Material.AIR)); //TODO message } } @EventHandler(ignoreCancelled = true) public void onDrop(PlayerDropItemEvent event) { Material itemType = event.getItemDrop().getItemStack().getType(); if(itemType == Material.SHULKER_SHELL || SHULKER_BOX_MATERIALS.contains(itemType)) { event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onDrop(EntityDeathEvent event) { Iterator it = event.getDrops().iterator(); while(it.hasNext()) { Material itemType = it.next().getType(); if(itemType == Material.SHULKER_SHELL || SHULKER_BOX_MATERIALS.contains(itemType)) { it.remove(); } } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/DropOnDeath.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Minepacks.Bukkit.API.Events.BackpackDropOnDeathEvent; import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.PlayerDeathEvent; public class DropOnDeath extends MinepacksListener { private final boolean honorKeepOnDeath; public DropOnDeath(Minepacks plugin) { super(plugin); honorKeepOnDeath = plugin.getConfiguration().getHonorKeepInventoryOnDeath(); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onDeath(PlayerDeathEvent event) { if(honorKeepOnDeath && event.getKeepInventory()) return; final Player player = event.getEntity(); if(plugin.isDisabled(player) != WorldBlacklistMode.None) return; if (!player.hasPermission(Permissions.KEEP_ON_DEATH)) { final Location location = player.getLocation(); plugin.getBackpack(player, backpack -> { BackpackDropOnDeathEvent event1 = new BackpackDropOnDeathEvent(player, backpack); plugin.getServer().getPluginManager().callEvent(event1); if(!event1.isCancelled()) { backpack.drop(location); } }); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/ItemFilter.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Bukkit.ItemNameResolver; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Message.Placeholder.Processors.ItemDisplayNamePlaceholderProcessor; import at.pcgamingfreaks.Bukkit.Message.Placeholder.Processors.ItemNamePlaceholderProcessor; import at.pcgamingfreaks.Bukkit.MinecraftMaterial; import at.pcgamingfreaks.Message.Placeholder.Placeholder; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.inventory.*; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; public class ItemFilter extends MinepacksListener implements at.pcgamingfreaks.Minepacks.Bukkit.API.ItemFilter { public final Message messageNotAllowedInBackpack; public final ItemNameResolver itemNameResolver; private final at.pcgamingfreaks.Bukkit.ItemFilter filter; public ItemFilter(final Minepacks plugin) { super(plugin); boolean whitelistMode = plugin.getConfiguration().isItemFilterModeWhitelist(); filter = new at.pcgamingfreaks.Bukkit.ItemFilter(whitelistMode); Collection filteredMaterials = plugin.getConfiguration().getItemFilterMaterials(); if(plugin.getConfiguration().isShulkerboxesPreventInBackpackEnabled() && !whitelistMode) { for(Material mat : DisableShulkerboxes.SHULKER_BOX_MATERIALS) { filteredMaterials.add(new MinecraftMaterial(mat, (short) -1)); } } filter.addFilteredMaterials(filteredMaterials); filter.addFilteredNames(plugin.getConfiguration().getItemFilterNames()); filter.addFilteredLore(plugin.getConfiguration().getItemFilterLore()); /*if[STANDALONE] itemNameResolver = new ItemNameResolver(); itemNameResolver.load(plugin, plugin.getConfiguration()); else[STANDALONE]*/ itemNameResolver = at.pcgamingfreaks.PluginLib.Bukkit.ItemNameResolver.getInstance(); /*end[STANDALONE]*/ messageNotAllowedInBackpack = plugin.getLanguage().getMessage("Ingame.NotAllowedInBackpack").placeholders(new Placeholder("ItemName", new ItemNamePlaceholderProcessor(itemNameResolver)), new Placeholder("ItemDisplayName", new ItemDisplayNamePlaceholderProcessor(itemNameResolver))); } @Override public boolean isItemBlocked(final @Nullable ItemStack item) { return filter.isItemBlocked(item); } @Override public void sendNotAllowedMessage(@NotNull Player player, @NotNull ItemStack itemStack) { messageNotAllowedInBackpack.send(player, itemStack); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemMove(InventoryMoveItemEvent event) { if(event.getDestination().getType() == InventoryType.CHEST && event.getDestination().getHolder() instanceof Backpack && isItemBlocked(event.getItem())) { if(event.getSource().getHolder() instanceof Player) { sendNotAllowedMessage((Player) event.getSource().getHolder(), event.getItem()); } event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemClick(InventoryClickEvent event) { if(!(event.getWhoClicked() instanceof Player)) return; if(event.getInventory().getType() == InventoryType.CHEST && event.getInventory().getHolder() instanceof Backpack) { Player player = (Player) event.getWhoClicked(); if(event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY && checkIsBlockedAndShowMessage(player, event.getCurrentItem())) { event.setCancelled(true); } else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getHotbarButton() != -1) { ItemStack item = event.getWhoClicked().getInventory().getItem(event.getHotbarButton()); if(checkIsBlockedAndShowMessage(player, item)) { event.setCancelled(true); } } else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getClick().name().equals("SWAP_OFFHAND")) { if(checkIsBlockedAndShowMessage(player, player.getInventory().getItemInOffHand())) { event.setCancelled(true); } } else if(!player.getInventory().equals(event.getClickedInventory()) && checkIsBlockedAndShowMessage(player, event.getCursor())) { event.setCancelled(true); } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemDrag(InventoryDragEvent event) { if(event.getInventory().getType() == InventoryType.CHEST && event.getInventory().getHolder() instanceof Backpack && (isItemBlocked(event.getOldCursor()) || isItemBlocked(event.getCursor())) && event.getRawSlots().containsAll(event.getInventorySlots())) { sendNotAllowedMessage((Player) event.getView().getPlayer(), event.getOldCursor()); event.setCancelled(true); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/ItemShortcut.java ================================================ /* * Copyright (C) 2025 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.HeadUtils; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.API.Events.InventoryClearedEvent; import at.pcgamingfreaks.Minepacks.Bukkit.API.WorldBlacklistMode; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.*; import org.bukkit.event.player.*; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.UUID; public class ItemShortcut extends MinepacksListener { private static final UUID MINEPACKS_UUID = UUID.nameUUIDFromBytes("Minepacks".getBytes()); private final String itemName, itemNameNoReset, value, openCommand; private final Message messageDoNotRemoveItem; private final boolean improveDeathChestCompatibility, blockAsHat, allowRightClickOnContainers, blockItemFromMoving; private final int preferredSlotId; private final Set containerMaterials = new HashSet<>(); public ItemShortcut(final @NotNull Minepacks plugin) { super(plugin); itemName = ChatColor.translateAlternateColorCodes('&', plugin.getConfiguration().getItemShortcutItemName()); itemNameNoReset = itemName.replace(ChatColor.RESET.toString(), ""); value = plugin.getConfiguration().getItemShortcutHeadValue(); improveDeathChestCompatibility = plugin.getConfiguration().isItemShortcutImproveDeathChestCompatibilityEnabled(); blockAsHat = plugin.getConfiguration().isItemShortcutBlockAsHatEnabled(); allowRightClickOnContainers = plugin.getConfiguration().isItemShortcutRightClickOnContainerAllowed(); preferredSlotId = plugin.getConfiguration().getItemShortcutPreferredSlotId(); blockItemFromMoving = plugin.getConfiguration().getItemShortcutBlockItemFromMoving(); openCommand = plugin.getLanguage().getCommandAliases("Backpack", "backpack")[0] + ' ' + plugin.getLanguage().getCommandAliases("Open", "open")[0]; messageDoNotRemoveItem = plugin.getLanguage().getMessage("Ingame.DontRemoveShortcut"); if(allowRightClickOnContainers) { containerMaterials.add(Material.CHEST); containerMaterials.add(Material.TRAPPED_CHEST); containerMaterials.add(Material.ENDER_CHEST); containerMaterials.add(Material.CRAFTING_TABLE); containerMaterials.add(Material.FURNACE); containerMaterials.add(Material.BLAST_FURNACE); containerMaterials.add(Material.DISPENSER); containerMaterials.add(Material.DROPPER); containerMaterials.add(Material.HOPPER); if(MCVersion.isNewerOrEqualThan(MCVersion.MC_1_11)) containerMaterials.addAll(DisableShulkerboxes.SHULKER_BOX_MATERIALS); } } public boolean isItemShortcut(final @Nullable ItemStack stack) { if(stack == null || stack.getType() != HeadUtils.HEAD_MATERIAL || !stack.hasItemMeta()) return false; String itemDisplayName = stack.getItemMeta().getDisplayName(); return itemDisplayName != null && itemNameNoReset.equals(itemDisplayName.replace(ChatColor.RESET.toString(), "")); } public void addItem(Player player) { if(player.hasPermission(Permissions.USE)) { boolean empty = false, item = false; for(ItemStack itemStack : player.getInventory()) { if(itemStack == null || itemStack.getType() == Material.AIR) empty = true; else if(isItemShortcut(itemStack)) { item = true; if(itemStack.getAmount() > 1) itemStack.setAmount(1); break; } } if(!item && empty) { if(preferredSlotId >= 0 && preferredSlotId < 36) { ItemStack stack = player.getInventory().getItem(preferredSlotId); if(stack == null || stack.getType() == Material.AIR) { player.getInventory().setItem(preferredSlotId, HeadUtils.fromBase64(value, itemName, MINEPACKS_UUID)); return; } } player.getInventory().addItem(HeadUtils.fromBase64(value, itemName, MINEPACKS_UUID)); } } else { for(ItemStack itemStack : player.getInventory()) { if(isItemShortcut(itemStack)) { player.getInventory().remove(itemStack); return; } } } } private void removeItem(Player player) { for(ItemStack itemStack : player.getInventory()) { if(isItemShortcut(itemStack)) { itemStack.setAmount(0); return; } } } //region Add backpack item @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onJoin(PlayerJoinEvent event) { if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return; Minepacks.getScheduler().runLater(() -> Minepacks.getScheduler().runAtEntity(event.getPlayer(), task -> addItem(event.getPlayer())), 2L); } @EventHandler(priority = EventPriority.MONITOR) public void onSpawn(PlayerRespawnEvent event) { if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return; Minepacks.getScheduler().runAtEntityLater(event.getPlayer(), task -> addItem(event.getPlayer()), 2L); } @EventHandler(priority = EventPriority.MONITOR) public void onWorldChange(final PlayerChangedWorldEvent event) { Player player = event.getPlayer(); Minepacks.getScheduler().runAtEntityLater(player, () -> { if(!player.isOnline()) return; if(player.hasPermission(Permissions.USE) && plugin.isDisabled(player) == WorldBlacklistMode.None) addItem(player); else removeItem(player); }, 2L); } @EventHandler(priority = EventPriority.MONITOR) public void onInventoryClear(InventoryClearedEvent event) { if(plugin.isDisabled(event.getPlayer()) != WorldBlacklistMode.None) return; addItem(event.getPlayer()); } //endregion //region Prevent placing of backpack item @EventHandler(priority = EventPriority.LOWEST) public void onItemInteract(PlayerInteractEvent event) { if ((event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK)) return; if(isItemShortcut(event.getItem())) { if(allowRightClickOnContainers && event.getAction() == Action.RIGHT_CLICK_BLOCK) { //noinspection ConstantConditions if(containerMaterials.contains(event.getClickedBlock().getType())) return; } event.getPlayer().performCommand(openCommand); event.setCancelled(true); } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onArmorStandManipulation(PlayerArmorStandManipulateEvent event) { if(isItemShortcut(event.getPlayerItem())) { event.getPlayer().performCommand(openCommand); event.setCancelled(true); } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onItemFrameInteract(PlayerInteractEntityEvent event) { Player player = event.getPlayer(); ItemStack item; if(MCVersion.isDualWieldingMC()) { item = (event.getHand() == EquipmentSlot.HAND) ? player.getInventory().getItemInMainHand() : player.getInventory().getItemInOffHand(); } else { item = player.getItemInHand(); } if(isItemShortcut(item)) { event.getPlayer().performCommand(openCommand); event.setCancelled(true); } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent event) { if(isItemShortcut(event.getItemInHand())) { event.getPlayer().performCommand(openCommand); event.setCancelled(true); } } //endregion //region Handle inventory actions @EventHandler(priority = EventPriority.LOWEST) public void onItemClick(InventoryClickEvent event) { if(event.getWhoClicked() instanceof Player) { final Player player = (Player) event.getWhoClicked(); if(isItemShortcut(event.getCurrentItem())) { if(event.getAction() == InventoryAction.SWAP_WITH_CURSOR) { if(plugin.isDisabled(player) != WorldBlacklistMode.None || !player.hasPermission(Permissions.USE) || !plugin.isPlayerGameModeAllowed(player)) return; Backpack backpack = plugin.getBackpackCachedOnly(player); if(backpack != null) { //TODO right click should place only one final ItemStack stack = event.getCursor(); if(plugin.getItemFilter() == null || !plugin.getItemFilter().isItemBlocked(stack)) { ItemStack full = backpack.addItem(stack); stack.setAmount((full == null) ? 0 : full.getAmount()); event.setCursor(full); event.setCancelled(true); } else { plugin.getItemFilter().messageNotAllowedInBackpack.send(player, plugin.getItemFilter().itemNameResolver.getName(stack)); } } } else if(event.getClick() == ClickType.RIGHT || event.getClick() == ClickType.SHIFT_RIGHT) { Minepacks.getScheduler().runAtEntity(player, task -> player.performCommand(openCommand)); event.setCancelled(true); } else if(event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) { event.setCancelled(true); messageDoNotRemoveItem.send(player); } if(blockItemFromMoving) event.setCancelled(true); } else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getHotbarButton() != -1) { ItemStack item = player.getInventory().getItem(event.getHotbarButton()); if(isItemShortcut(item)) { event.setCancelled(true); messageDoNotRemoveItem.send(player); } } else if((event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP) && event.getClick().name().equals("SWAP_OFFHAND")) { if(isItemShortcut(player.getInventory().getItemInOffHand())) { event.setCancelled(true); messageDoNotRemoveItem.send(player); } } else if(isItemShortcut(event.getCursor())) { if(!player.getInventory().equals(event.getClickedInventory())) { event.setCancelled(true); messageDoNotRemoveItem.send(player); } else if(event.getSlotType() == InventoryType.SlotType.ARMOR && blockAsHat) { event.setCancelled(true); } } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemDrag(InventoryDragEvent event) { if(!event.getInventory().equals(event.getWhoClicked().getInventory()) && event.getRawSlots().containsAll(event.getInventorySlots())) { if(isItemShortcut(event.getCursor()) || isItemShortcut(event.getOldCursor())) { event.setCancelled(true); messageDoNotRemoveItem.send(event.getWhoClicked()); } } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onDropItem(PlayerDropItemEvent event) { if(isItemShortcut(event.getItemDrop().getItemStack())) { event.setCancelled(true); messageDoNotRemoveItem.send(event.getPlayer()); } } //endregion /** * Removes the backpack item form the drops on death */ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onDeath(PlayerDeathEvent event) { //region prevent drop Iterator itemStackIterator = event.getDrops().iterator(); while(itemStackIterator.hasNext()) { if(isItemShortcut(itemStackIterator.next())) { itemStackIterator.remove(); break; } } //endregion if(improveDeathChestCompatibility) { // improveDeathChestCompatibility for(ItemStack itemStack : event.getEntity().getInventory()) { if(isItemShortcut(itemStack)) { itemStack.setAmount(0); itemStack.setType(Material.AIR); } } } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/MinepacksListener.java ================================================ /* * Copyright (C) 2017 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import lombok.AllArgsConstructor; import org.bukkit.event.Listener; @AllArgsConstructor abstract class MinepacksListener implements Listener { protected final Minepacks plugin; } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Listener/WorldBlacklistUpdater.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Listener; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.event.EventHandler; import org.bukkit.event.world.WorldInitEvent; import org.jetbrains.annotations.NotNull; import java.util.Locale; public class WorldBlacklistUpdater extends MinepacksListener { public WorldBlacklistUpdater(final @NotNull Minepacks plugin) { super(plugin); } @EventHandler public void onWorldInit(final WorldInitEvent event) { String worldName = event.getWorld().getName().toLowerCase(Locale.ROOT); if(!plugin.getConfiguration().getWorldFilteredList().contains(worldName)) { plugin.getWorldBlacklist().add(worldName); } } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Minepacks.java ================================================ /* * Copyright (C) 2025 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.Bukkit.Config.PermissionLoader; import at.pcgamingfreaks.Bukkit.MCVersion; import at.pcgamingfreaks.Bukkit.ManagedUpdater; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Util.InventoryUtils; import at.pcgamingfreaks.Bukkit.Util.Utils; import at.pcgamingfreaks.ConsoleColor; import at.pcgamingfreaks.Minepacks.Bukkit.API.*; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import at.pcgamingfreaks.Minepacks.Bukkit.Command.CommandManager; import at.pcgamingfreaks.Minepacks.Bukkit.Command.InventoryClearCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Command.ShortcutCommand; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Config; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Database; import at.pcgamingfreaks.Minepacks.Bukkit.Database.Language; import at.pcgamingfreaks.Minepacks.Bukkit.Listener.*; import at.pcgamingfreaks.Minepacks.Bukkit.Listener.ItemFilter; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholder.PlaceholderManager; import at.pcgamingfreaks.Minepacks.Bukkit.SpecialInfoWorker.NoDatabaseWorker; import at.pcgamingfreaks.Minepacks.MagicValues; import at.pcgamingfreaks.Plugin.IPlugin; import at.pcgamingfreaks.ServerType; import at.pcgamingfreaks.Updater.UpdateResponseCallback; import at.pcgamingfreaks.Util.StringUtils; import at.pcgamingfreaks.Version; import at.pcgf.libs.com.tcoded.folialib.FoliaLib; import at.pcgf.libs.com.tcoded.folialib.impl.PlatformScheduler; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.OfflinePlayer; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import lombok.Getter; import java.io.File; import java.util.Collection; import java.util.Locale; import java.util.Set; public class Minepacks extends JavaPlugin implements MinepacksPlugin, IPlugin { @Getter private static Minepacks instance = null; @Getter private static FoliaLib foliaLib = null; private ManagedUpdater updater = null; private Config config; private Language lang; @Getter private Database database; public Message messageNoPermission, messageInvalidBackpack, messageWorldDisabled, messageNotFromConsole, messageNotANumber; private int maxSize; @Getter private Set worldBlacklist; private WorldBlacklistMode worldBlacklistMode; private ItemsCollector collector; private CommandManager commandManager; private InventoryClearCommand inventoryClearCommand; private Collection gameModes; private CooldownManager cooldownManager = null; private ItemFilter itemFilter = null; private Sound openSound = null; private ItemShortcut shortcut = null; @Getter private PlaceholderManager placeholderManager = null; @Override public boolean isRunningInStandaloneMode() { /*if[STANDALONE] return true; else[STANDALONE]*/ return false; /*end[STANDALONE]*/ } @Override public void onEnable() { checkOldDataFolder(); if(!checkPCGF_PluginLib()) return; if (MCVersion.isNewerOrEqualThan(MCVersion.MC_1_19_3) && ServerType.isPaperCompatible()) { PermissionLoader.loadPermissionsFromPlugin(this); } updater = new ManagedUpdater(this); instance = this; foliaLib = new FoliaLib(this); config = new Config(this); updater.setChannel(config.getUpdateChannel()); if(config.useUpdater()) updater.update(); if(!checkMcVersion()) return; lang = new Language(this); load(); getLogger().info(StringUtils.getPluginEnabledMessage(getDescription().getName())); } private boolean checkMcVersion() { if (MCVersion.isNewerThan(MCVersion.MC_NMS_1_20_R3) && ServerType.isPaperCompatible()) { getLogger().warning("Paper support is experimental! Use at your own risk!"); getLogger().warning("No guarantee for data integrity! Backup constantly!"); } // DO NOT REMOVE THIS! This is protecting your data! To add support for a new version, update PCGF PluginLib and then update the last version check! if (MCVersion.is(MCVersion.UNKNOWN) || !MCVersion.isUUIDsSupportAvailable() || MCVersion.isNewerThan(MCVersion.MC_NMS_26_1_R1)) { this.warnOnVersionIncompatibility(); this.setEnabled(false); return false; } return true; } private boolean checkPCGF_PluginLib() { // Check if running as standalone edition /*if[STANDALONE] getLogger().info("Starting Minepacks in standalone mode!"); if(getServer().getPluginManager().isPluginEnabled("PCGF_PluginLib")) { getLogger().info("You do have the PCGF_PluginLib installed. You may consider switching to the default version of the plugin to reduce memory load and unlock additional features."); } else[STANDALONE]*/ // Not standalone so we should check the version of the PluginLib if(at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getVersion().olderThan(new Version(MagicValues.MIN_PCGF_PLUGIN_LIB_VERSION))) { getLogger().warning("You are using an outdated version of the PCGF PluginLib! Please update it!"); setEnabled(false); return false; } /*end[STANDALONE]*/ return true; } private void checkOldDataFolder() { if(!getDataFolder().exists()) { File oldPluginFolder = new File(getDataFolder().getParentFile(), "MinePacks"); if(oldPluginFolder.exists() && !oldPluginFolder.renameTo(getDataFolder())) { getLogger().warning("Failed to rename the plugins data-folder.\n" + "Please rename the \"MinePacks\" folder to \"Minepacks\" and restart the server, to move your data from Minepacks V1.X to Minepacks V2.X!"); } } } @Override public void onDisable() { if(config == null) return; if(config.useUpdater()) updater.update(); unload(); updater.waitForAsyncOperation(); // Wait for an update to finish getLogger().info(StringUtils.getPluginDisabledMessage(getDescription().getName())); instance = null; } public void update(final @Nullable UpdateResponseCallback updateResponseCallback) { updater.update(updateResponseCallback); } private void load() { updater.setChannel(config.getUpdateChannel()); lang.load(config); database = Database.getDatabase(this); if(database == null) { new NoDatabaseWorker(this); return; } maxSize = config.getBackpackMaxSize(); at.pcgamingfreaks.Minepacks.Bukkit.Backpack.setShrinkApproach(config.getShrinkApproach()); at.pcgamingfreaks.Minepacks.Bukkit.Backpack.setTitle(config.useDynamicBPTitle() ? config.getBPTitle() : config.getBPTitleOther(), config.getBPTitleOther()); at.pcgamingfreaks.Minepacks.Bukkit.Backpack.setMessageBackpackShrunk(lang.getMessage("Ingame.BackpackShrunk")); messageNotFromConsole = lang.getMessage("NotFromConsole"); messageNoPermission = lang.getMessage("Ingame.NoPermission"); messageInvalidBackpack = lang.getMessage("Ingame.InvalidBackpack"); messageWorldDisabled = lang.getMessage("Ingame.WorldDisabled"); messageNotANumber = lang.getMessage("Ingame.NaN"); commandManager = new CommandManager(this); if(config.isInventoryManagementClearCommandEnabled()) inventoryClearCommand = new InventoryClearCommand(this); //region register events PluginManager pluginManager = getServer().getPluginManager(); pluginManager.registerEvents(new BackpackEventListener(this), this); if(config.getDropOnDeath()) pluginManager.registerEvents(new DropOnDeath(this), this); if(config.isItemFilterEnabled()) { itemFilter = new ItemFilter(this); pluginManager.registerEvents(itemFilter, this); } if(config.isShulkerboxesDisable()) pluginManager.registerEvents(new DisableShulkerboxes(this), this); if(config.isItemShortcutEnabled()) { shortcut = new ItemShortcut(this); pluginManager.registerEvents(shortcut, this); commandManager.registerSubCommand(new ShortcutCommand(this, shortcut)); } else shortcut = null; if(config.isWorldWhitelistMode()) pluginManager.registerEvents(new WorldBlacklistUpdater(this), this); //endregion if(config.getFullInvCollect() || config.isFullInvToggleAllowed()) collector = new ItemsCollector(this); worldBlacklist = config.getWorldBlacklist(); worldBlacklistMode = (worldBlacklist.isEmpty()) ? WorldBlacklistMode.None : config.getWorldBlockMode(); gameModes = config.getAllowedGameModes(); if(config.getCommandCooldown() > 0) cooldownManager = new CooldownManager(this); openSound = config.getOpenSound(); placeholderManager = new PlaceholderManager(this); } private void unload() { if(lang == null) return; if(inventoryClearCommand != null) { inventoryClearCommand.close(); inventoryClearCommand = null; } if (placeholderManager != null) { placeholderManager.close(); placeholderManager = null; } if(collector != null) collector.close(); if(commandManager != null) commandManager.close(); if(collector != null) collector.cancel(); if(database != null) database.close(); // Close the DB connection, we won't need them any longer HandlerList.unregisterAll(this); // Stop the listeners if(cooldownManager != null) cooldownManager.close(); cooldownManager = null; getScheduler().cancelAllTasks(); // Kill all running task itemFilter = null; } public void reload() { unload(); config.reload(); load(); } public void warnOnVersionIncompatibility() { getLogger().warning(ConsoleColor.RED + "################################" + ConsoleColor.RESET); getLogger().warning(ConsoleColor.RED + String.format("Your minecraft version (MC %1$s) is currently not compatible with this plugins version (%2$s). " + "Please check for updates!", Bukkit.getServer().getVersion(), getDescription().getVersion()) + ConsoleColor.RESET); getLogger().warning(ConsoleColor.RED + "################################" + ConsoleColor.RESET); Utils.blockThread(5); } public Config getConfiguration() { return config; } public Language getLanguage() { return lang; } @Override public void openBackpack(@NotNull final Player opener, @NotNull final OfflinePlayer owner, final boolean editable) { openBackpack(opener, owner, editable, null); } @Override public void openBackpack(@NotNull final Player opener, @Nullable final Backpack backpack, boolean editable) { openBackpack(opener, backpack, editable, null); } @Override public void openBackpack(@NotNull Player opener, @NotNull OfflinePlayer owner, boolean editable, @Nullable String title) { database.getBackpack(owner, backpack -> openBackpack(opener, backpack, editable, title)); } @Override public void openBackpack(@NotNull Player opener, @Nullable Backpack backpack, boolean editable, @Nullable String title) { WorldBlacklistMode disabled = isDisabled(opener); if(disabled != WorldBlacklistMode.None) { if (disabled == WorldBlacklistMode.Message) messageWorldDisabled.send(opener); else if (disabled == WorldBlacklistMode.MissingPermission) messageNoPermission.send(opener); return; } if(backpack == null) { messageInvalidBackpack.send(opener); return; } //noinspection ObjectEquality if(InventoryUtils.getPlayerTopInventory(opener).getHolder() == backpack) return; // == is fine as there is only one instance of each backpack if(openSound != null) { opener.playSound(opener.getLocation(), openSound, 1, 0); } backpack.open(opener, editable); } @Override public @Nullable Backpack getBackpackCachedOnly(@NotNull OfflinePlayer owner) { return database.getBackpack(owner); } @Override public void getBackpack(@NotNull OfflinePlayer owner, @NotNull Callback callback) { database.getBackpack(owner, callback); } @Override public void getBackpack(@NotNull final OfflinePlayer owner, @NotNull final Callback callback, boolean createNewIfNotExists) { database.getBackpack(owner, callback, createNewIfNotExists); } @Override public MinepacksCommandManager getCommandManager() { /*if[STANDALONE] return null; else[STANDALONE]*/ return commandManager; /*end[STANDALONE]*/ } public int getBackpackPermSize(Player player) { for(int i = maxSize; i > 1; i--) { if(player.hasPermission("backpack.size." + i)) return i * 9; } return 9; } @Override public @NotNull WorldBlacklistMode isDisabled(final @NotNull Player player) { if(worldBlacklistMode == WorldBlacklistMode.None || (worldBlacklistMode != WorldBlacklistMode.NoPlugin && player.hasPermission(Permissions.IGNORE_WORLD_BLACKLIST))) return WorldBlacklistMode.None; if(worldBlacklist.contains(player.getWorld().getName().toLowerCase(Locale.ROOT))) return worldBlacklistMode; return WorldBlacklistMode.None; } @Override public boolean isPlayerGameModeAllowed(final @NotNull Player player) { return gameModes.contains(player.getGameMode()) || player.hasPermission(Permissions.IGNORE_GAME_MODE); } public @Nullable CooldownManager getCooldownManager() { return cooldownManager; } @Override public @Nullable ItemFilter getItemFilter() { return itemFilter; } @Override public boolean isBackpackItem(final @Nullable ItemStack itemStack) { if(shortcut == null) return false; return shortcut.isItemShortcut(itemStack); } public ItemsCollector getItemsCollector() { return collector; } public static PlatformScheduler getScheduler() { return foliaLib.getScheduler(); } @Override public @NotNull Version getVersion() { return new Version(getDescription().getVersion()); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Permissions.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import lombok.SneakyThrows; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; public class Permissions { public static final String BASE = "backpack."; public static final String USE = BASE + "use"; public static final String SORT = BASE + "sort"; public static final String CLEAN = BASE + "clean"; public static final String CLEAN_OTHER = BASE + "clean.other"; public static final String FULL_PICKUP = BASE + "fullpickup"; public static final String PICKUP_TOGGLE = BASE + "fullpickup.toggle"; public static final String OTHERS = BASE + "others"; public static final String OTHERS_EDIT = BASE + "others.edit"; public static final String KEEP_ON_DEATH = BASE + "keepOnDeath"; public static final String NO_COOLDOWN = BASE + "noCooldown"; public static final String IGNORE_GAME_MODE = BASE + "ignoreGameMode"; public static final String IGNORE_WORLD_BLACKLIST = BASE + "ignoreWorldBlacklist"; public static final String UPDATE = BASE + "update"; public static final String RELOAD = BASE + "reload"; public static final String MIGRATE = BASE + "migrate"; public static final String BACKUP = BASE + "backup"; public static final String RESTORE = BASE + "restore"; public static final String VERSION = BASE + "version"; public static final String INVENTORY_CLEAR = "clearInventory"; public static final String INVENTORY_CLEAR_OTHER = "clearInventory.other"; @SneakyThrows public static List getPermissions() { Field[] fields = Permissions.class.getDeclaredFields(); List permissions = new ArrayList<>(fields.length); for(Field field : fields) { if (field.getType().equals(String.class) && Modifier.isStatic(field.getModifiers())) { String val = ((String) field.get(null)); if (!val.endsWith(".")) { permissions.add(val); } } } for (int i = 1; i < 10; i++) { permissions.add("backpack.size." + i); } return permissions; } private Permissions() {} } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Placeholder/PlaceholderManager.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Placeholder; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Placeholder.Replacer.AutoPickupEnabled; public final class PlaceholderManager extends at.pcgamingfreaks.Bukkit.Placeholder.PlaceholderManager { public PlaceholderManager(Minepacks plugin) { super(plugin); } @Override protected void generatePlaceholdersMap() { Minepacks plugin = (Minepacks) getPlugin(); registerPlaceholder(new AutoPickupEnabled(plugin)); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Placeholder/Replacer/AutoPickupEnabled.java ================================================ /* * Copyright (C) 2023 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.Placeholder.Replacer; import at.pcgamingfreaks.Bukkit.Placeholder.PlaceholderName; import at.pcgamingfreaks.Bukkit.Placeholder.PlaceholderReplacerBase; import at.pcgamingfreaks.Minepacks.Bukkit.ItemsCollector; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; @PlaceholderName(aliases = "IsAutoPickupEnabled") public class AutoPickupEnabled extends PlaceholderReplacerBase { private final Minepacks plugin; public AutoPickupEnabled(Minepacks mp) { this.plugin = mp; } @Override public @Nullable String replace(OfflinePlayer player) { ItemsCollector collector = plugin.getItemsCollector(); if (collector != null) { if (player instanceof Player) { return collector.canUseAutoPickup((Player) player) ? "true" : "false"; } return "offline"; } return "disabled"; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Placeholders.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.Bukkit.Message.Placeholder.Processors.PlayerDisplayNamePlaceholderProcessor; import at.pcgamingfreaks.Bukkit.Message.Placeholder.Processors.PlayerNamePlaceholderProcessor; import at.pcgamingfreaks.Message.Placeholder.Placeholder; import org.jetbrains.annotations.NotNull; public class Placeholders { private Placeholders(){} public static final @NotNull String[] PAGE_OPTIONS = { "CurrentPage", "MaxPage", "MainCommand", "SubCommand", "PrevPage", "NextPage" }; public static final @NotNull Placeholder[] PLAYER_NAME = mkPlayerName(""); public static @NotNull Placeholder[] mkPlayerName(final @NotNull String prefix) { return mkPlayerName(prefix, "", false); } public static @NotNull Placeholder[] mkPlayerName(final @NotNull String prefix, final @NotNull String suffix) { return mkPlayerName(prefix, suffix, false); } public static @NotNull Placeholder[] mkPlayerName(final @NotNull String prefix, final @NotNull String suffix, final boolean regex) { return new Placeholder[]{ new Placeholder(prefix + "Name" + suffix, PlayerNamePlaceholderProcessor.INSTANCE, regex), new Placeholder(prefix + "DisplayName" + suffix, PlayerDisplayNamePlaceholderProcessor.INSTANCE, regex) }; } public static @NotNull Placeholder[] mkPlayerNameRegex(final @NotNull String prefix) { return mkPlayerName(prefix, "", true); } public static @NotNull Placeholder[] mkPlayerNameRegex(final @NotNull String prefix, final @NotNull String suffix) { return mkPlayerName(prefix, suffix, true); } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/ShrinkApproach.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; public enum ShrinkApproach { FAST, COMPRESS, SORT; } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/SpecialInfoWorker/NoDatabaseWorker.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.SpecialInfoWorker; import at.pcgamingfreaks.Bukkit.Command.RegisterablePluginCommand; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Bukkit.Message.MessageBuilder; import at.pcgamingfreaks.Message.MessageColor; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import at.pcgamingfreaks.Minepacks.Bukkit.Permissions; import at.pcgamingfreaks.Reflection; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; /** * This worker will inform the admin that the plugin failed to connect to the database, he hopefully is able to solve the problem. * It registers a new command that only allows to reload the plugin to prevent unnecessary downtime for the server cause of restarts. */ public class NoDatabaseWorker extends SpecialInfoBase implements CommandExecutor { private final Minepacks plugin; private final RegisterablePluginCommand command; private final Message messageDBProblem; public NoDatabaseWorker(final @NotNull Minepacks plugin) { super(plugin, Permissions.RELOAD); this.plugin = plugin; Bukkit.getPluginManager().registerEvents(this, plugin); command = new RegisterablePluginCommand(plugin, "backpack"); command.registerCommand(); command.setExecutor(this); messageDBProblem = new MessageBuilder("Minepacks", MessageColor.GOLD).append(" failed to connect to its database!", MessageColor.RED).appendNewLine() .append("Please check your configuration and reload the plugin (", MessageColor.RED).append("/backpack reload", MessageColor.BLUE).command("/backpack reload").append(")!", MessageColor.RED).getMessage(); } @Override protected void sendMessage(Player player) { messageDBProblem.send(player); } @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command cmd, @NotNull String s, String[] strings) { if(strings.length != 1 || !strings[0].equalsIgnoreCase("reload")) { commandSender.sendMessage(MessageColor.RED + "Only \"/backpack reload\" is available at the moment!"); } else { if(commandSender.hasPermission(Permissions.RELOAD)) { command.unregisterCommand(); HandlerList.unregisterAll(this); try { plugin.getConfiguration().reload(); Reflection.getMethod(plugin.getClass(), "load").invoke(plugin); } catch(Exception e) { e.printStackTrace(); } } else { commandSender.sendMessage(MessageColor.RED + "You don't have the permission to do that!"); } } return true; } } ================================================ FILE: Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/SpecialInfoWorker/SpecialInfoBase.java ================================================ /* * Copyright (C) 2025 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.SpecialInfoWorker; import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.java.JavaPlugin; public abstract class SpecialInfoBase implements Listener { private final JavaPlugin plugin; private final String permission; protected SpecialInfoBase(final JavaPlugin plugin, final String permission) { this.plugin = plugin; this.permission = permission; } @EventHandler public void onJoin(final PlayerJoinEvent event) { if(event.getPlayer().hasPermission(permission)) { Minepacks.getScheduler().runLater(() -> Minepacks.getScheduler().runAtEntity(event.getPlayer(), task -> { if(event.getPlayer().isOnline()) { sendMessage(event.getPlayer()); } }), 3 * 20L); // Run with a 3 seconds delay } } protected abstract void sendMessage(final Player player); } ================================================ FILE: Minepacks/test/src/at/pcgamingfreaks/Minepacks/Bukkit/PermissionsTest.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit; import at.pcgamingfreaks.yaml.YAML; import at.pcgamingfreaks.yaml.YamlInvalidContentException; import at.pcgamingfreaks.yaml.YamlKeyNotFoundException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.Collection; import java.util.HashSet; import static org.junit.jupiter.api.Assertions.assertTrue; public class PermissionsTest { private static Collection permissions; @BeforeAll public static void setup() throws IllegalAccessException { // Collect all permissions defined in the Permissions class permissions = new HashSet<>(); for(Field declaredField : Permissions.class.getDeclaredFields()) { if(declaredField.getName().equals("BASE") || declaredField.getName().equals("SIZE_BASE")) continue; permissions.add((String) declaredField.get(null)); } } private int countKeysStartingWith(Collection keys, String startsWith) { int count = 0; for(String key : keys) { if(key.startsWith(startsWith)) count++; } return count; } @Test public void testPermissionsInPluginYaml() throws IOException, YamlInvalidContentException, YamlKeyNotFoundException { YAML pluginYaml = new YAML(new File("resources/plugin.yml")); YAML permissionsYaml = pluginYaml.getSection("permissions"); // Check if all permissions are defined in the plugin.yml for(String permission : permissions) { assertTrue(permissionsYaml.isSet(permission + ".description"), "The plugin.yml should contain the permission " + permission); } // Check if all the permissions defined in the plugin.yml are also defined in the Permissions class Collection keys = permissionsYaml.getKeys(true); for(String key : keys) { if(!key.endsWith("description")) continue; String perm = key.substring(0, key.length() - 12); if(perm.contains(".size.")) continue; // Ignore size permissions if(countKeysStartingWith(keys, perm + ".children") > 1) continue; // Skip all the permissions that are just for permission grouping assertTrue(permissions.contains(perm), "The plugin.yml should not contain the permission " + perm); } } } ================================================ FILE: Minepacks-API/README.md ================================================ [banner]: https://pcgamingfreaks.at/images/minepacks.png [spigot]: https://www.spigotmc.org/resources/minepacks.19286/ [license]: https://github.com/GeorgH93/Minepacks/blob/master/LICENSE [licenseImg]: https://img.shields.io/github/license/GeorgH93/Minepacks.svg [ci]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/ [ciImg]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/badge/icon [apiVersionImg]: https://img.shields.io/badge/dynamic/xml.svg?label=api-version&query=%2F%2Frelease[1]&url=https%3A%2F%2Frepo.pcgamingfreaks.at%2Frepository%2Fmaven-releases%2Fat%2Fpcgamingfreaks%2FMinepacks-API%2Fmaven-metadata.xml [apiJavaDoc]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/javadoc/ [apiBuilds]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/ [![Logo][banner]][spigot] This branch holds the API for the Minepacks plugin. [![ciImg]][ci] [![apiVersionImg]][apiJavaDoc] [![licenseImg]][license] ## Adding it to your plugin: ### Maven: The API is available through maven. #### Repository: ``` pcgf-repo https://repo.pcgamingfreaks.at/repository/maven-everything ``` #### Dependency: ``` at.pcgamingfreaks Minepacks-API 2.2 ``` ### Build from source: ``` git clone https://github.com/GeorgH93/Minepacks.git cd Minepacks mvn -pl Minepacks-API ``` ## Usage: ### Get access to the API: ```java public static MinepacksPlugin getMinepacks() { Plugin bukkitPlugin = Bukkit.getPluginManager().getPlugin("Minepacks"); if(!(bukkitPlugin instanceof MinepacksPlugin)) { // Do something if Minepacks is not available return null; } return (MinepacksPlugin) bukkitPlugin; } ``` You can now use the returned `MinepacksPlugin` object to interact with the Minepacks plugin. ### Access a players backpack inventory: ```java public static Inventory getPlayerBackpackInventory(Player player) { Backpack bp = getMinepacks().getBackpackCachedOnly(player); if(bp == null) return null; //Backpack not loaded (retry later) return bp.getInventory(); } ``` This will return null if the backpack is not loaded or the inventory of the backpack if the backpack is already loaded. ## Links: * [JavaDoc][apiJavaDoc] * [API Build Server][apiBuilds] ================================================ FILE: Minepacks-API/pom.xml ================================================ 4.0.0 Minepacks-API Minepacks-Parent at.pcgamingfreaks ${revision} .. ${revision} jar Minepacks-API API for the Bukkit/Spigot plugin Minepacks. at.pcgamingfreaks PluginLib ${pcgfPluginLibVersion} provided clean install src org.apache.maven.plugins maven-source-plugin 2.2.1 attach-sources jar org.apache.maven.plugins maven-javadoc-plugin 3.1.1 attach-javadocs jar -Xdoclint:none 8 ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/Backpack.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.UUID; @SuppressWarnings("unused") public interface Backpack extends InventoryHolder { /** * Gets the owner of the backpack. * * @return The owner of the backpack; * @deprecated Use the {@link Backpack#getOwnerId()} function instead. */ @Deprecated @NotNull OfflinePlayer getOwner(); /** * Gets the id of the player owning the backpack. * * @return The uuid of the owning player. */ UUID getOwnerId(); @Nullable Player getOwnerPlayer(); /** * Let a given player open this backpack. * * @param player The player who opens the backpack. * @param editable Defines if the player who has opened the backpack can change the items inside. */ void open(@NotNull Player player, boolean editable); /** * Let a given player open this backpack. * * @param player The player who opens the backpack. * @param editable Defines if the player who has opened the backpack can change the items inside. * @param title Custom title for the backpack (will be shown to the player who opened the backpack. */ void open(@NotNull Player player, boolean editable, @Nullable String title); /** * Checks if the backpack is currently opened by a player. * * @return True if the backpack is open, false if not. */ boolean isOpen(); /** * Checks if a player can change the content of the backpack. * * @param player The player to be checked. * @return True if he can change the content, false if not. */ boolean canEdit(@NotNull Player player); /** * Gets the size of the backpack. * * @return The size of the backpack. */ int getSize(); /** * Checks if the backpack has changed since it was last saved. * * @return True if it has been changed, false if not. */ boolean hasChanged(); /** * Marks that the content of the backpack a changed. It will be saved when the next player closes the backpack or before it gets removed from the cache. */ void setChanged(); /** * Forces the backpack to be saved */ void save(); /** * Removes all items from the backpack. */ void clear(); /** * Drops the content of the backpack to the ground on a given location. * * @param location The location the content of the backpack should be dropped to. */ void drop(Location location); /** * @param stack The item stack that should be added to the backpack. * @return null if the entire item stack has been added. An item stack containing the items that did not fit into the backpack. */ default @Nullable ItemStack addItem(ItemStack stack) { Map left = addItems(stack); if(left.isEmpty()) return null; return left.get(0); } /** * @param itemStacks The item that should be added to the backpack. * @return A HashMap containing items that didn't fit. The key is the number of the added item */ default @NotNull Map addItems(ItemStack... itemStacks) { setChanged(); return getInventory().addItem(itemStacks); } static boolean isBackpack(@Nullable Inventory inventory) { return inventory instanceof Backpack; } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/Callback.java ================================================ /* * Copyright (C) 2019 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; public interface Callback { void onResult(T done); default void onFail() { /* In most cases this can be ignored since it will not happen with most db queries used */ } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/Events/BackpackDropOnDeathEvent.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API.Events; import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import lombok.Getter; import lombok.Setter; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; /** * Event is triggered bevor the backpacks content is dropped to the ground! */ public class BackpackDropOnDeathEvent extends Event implements Cancellable { @Getter @Setter private boolean cancelled = false; @Getter private final Player owner; @Getter private final Backpack backpack; public BackpackDropOnDeathEvent(final @NotNull Player owner, final @NotNull Backpack backpack) { this.owner = owner; this.backpack = backpack; } // Bukkit handler stuff private static final HandlerList handlers = new HandlerList(); @Override public @NotNull HandlerList getHandlers() { return getHandlerList(); } public static HandlerList getHandlerList() { return handlers; } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/Events/InventoryClearEvent.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API.Events; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; @RequiredArgsConstructor() public class InventoryClearEvent extends Event implements Cancellable { @Getter @Setter private boolean cancelled = false; /** * The player whose inventory should be cleared. */ @Getter private final Player player; /** * The command sender who has requested the inventory to be cleared. */ @Getter private final CommandSender sender; // Bukkit handler stuff private static final HandlerList handlers = new HandlerList(); @Override public @NotNull HandlerList getHandlers() { return getHandlerList(); } public static HandlerList getHandlerList() { return handlers; } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/Events/InventoryClearedEvent.java ================================================ /* * Copyright (C) 2022 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API.Events; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; @RequiredArgsConstructor() public class InventoryClearedEvent extends Event { /** * The player whose inventory has been cleared. */ @Getter private final Player player; /** * The command sender who has requested the inventory to be cleared. */ @Getter private final CommandSender sender; // Bukkit handler stuff private static final HandlerList handlers = new HandlerList(); @Override public @NotNull HandlerList getHandlers() { return getHandlerList(); } public static HandlerList getHandlerList() { return handlers; } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/ItemFilter.java ================================================ /* * Copyright (C) 2019 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @SuppressWarnings("unused") public interface ItemFilter { /** * @param item The item that should be checked. * @return True if the item is not allowed. False if the item is allowed. */ @Contract("null->false") boolean isItemBlocked(@Nullable ItemStack item); /** * @param player The player that should receive the message that the item is not allowed. * @param itemStack The item that is not allowed. Will be used for the name. */ void sendNotAllowedMessage(@NotNull Player player, @NotNull ItemStack itemStack); /** * @param player The player that should receive the message if the item is not allowed. * @param itemStack The item that should be checked. * @return True if the item is not allowed. False if the item is allowed. */ default boolean checkIsBlockedAndShowMessage(@NotNull Player player, @Nullable ItemStack itemStack) { if(isItemBlocked(itemStack)) { sendNotAllowedMessage(player, itemStack); return true; } return false; } } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/MinepacksCommand.java ================================================ /* * Copyright (C) 2024 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; import at.pcgamingfreaks.Bukkit.Command.SubCommand; import at.pcgamingfreaks.Bukkit.Message.Message; import at.pcgamingfreaks.Command.HelpData; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; /** * Only available if the plugin is not running in standalone mode! */ public abstract class MinepacksCommand extends SubCommand { @SuppressWarnings("FieldMayBeFinal") private static MinepacksPlugin minepacksPlugin = null; // Will be set by reflection @SuppressWarnings("FieldMayBeFinal") private static Object minepacksCommandManager = null; @SuppressWarnings("FieldMayBeFinal") private static Method showHelp = null; // Will be set by reflection @SuppressWarnings("FieldMayBeFinal") // Will be overwritten by reflection private static Message messageNoPermission = new Message(ChatColor.RED + "You don't have the permission to do that."); @SuppressWarnings("FieldMayBeFinal") // Will be overwritten by reflection private static Message messageNotFromConsole = new Message(ChatColor.RED + "This command can't be used from console!"); protected final JavaPlugin plugin; private final boolean playerOnly; //region Constructors /** * Creates a new command instance. * * @param plugin The plugin owning the command. * @param name The command used. * @param description The description of the command. * @param aliases List of aliases for that command. */ protected MinepacksCommand(@NotNull JavaPlugin plugin, @NotNull String name, @NotNull String description, @Nullable String... aliases) { this(plugin, name, description, null, aliases); } /** * Creates a new command instance. * * @param plugin The plugin owning the command. * @param name The command used. * @param description The description of the command. * @param permission The permission to be checked for this command. Players without the permission neither can use the command nor will they see it in help. * @param aliases List of aliases for that command. */ protected MinepacksCommand(@NotNull JavaPlugin plugin, @NotNull String name, @NotNull String description, @Nullable String permission, @Nullable String... aliases) { this(plugin, name, description, permission, false, aliases); } /** * Creates a new command instance. * * @param plugin The plugin owning the command. * @param name The command used. * @param description The description of the command. * @param permission The permission to be checked for this command. Players without the permission neither can use the command nor will they see it in help. * @param playerOnly Limits the command to players, console can't use and can't see the command. * @param aliases List of aliases for that command. */ protected MinepacksCommand(@NotNull JavaPlugin plugin, @NotNull String name, @NotNull String description, @Nullable String permission, boolean playerOnly, @Nullable String... aliases) { super(name, description, permission, aliases); this.plugin = plugin; this.playerOnly = playerOnly; } //endregion /** * Gets the instance of the marriage master plugin. * * @return The instance of the marriage master plugin. */ protected @NotNull MinepacksPlugin getMinepacksPlugin() { return minepacksPlugin; } //region Command Stuff /** * Executes some basic checks and runs the command afterwards. * * @param sender Source of the command. * @param mainCommandAlias Alias of the plugins main command which was used. * @param alias Alias of the command which has been used. * @param args Passed command arguments. */ @Override public void doExecute(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String... args) { if(playerOnly && !(sender instanceof Player)) { messageNotFromConsole.send(sender); } else if(getPermission() != null && !sender.hasPermission(getPermission())) { messageNoPermission.send(sender); } else { execute(sender, mainCommandAlias, alias, args); } } /** * Executes some basic checks and generates list for tab completion. * * @param sender Source of the command. * @param mainCommandAlias Alias of the plugins main command which has been used. * @param alias The alias used. * @param args The arguments passed to the command, including final partial argument to be completed and command label. * @return A List of possible completions for the final argument, or null to default to the command executor. */ @Override public List doTabComplete(@NotNull CommandSender sender, @NotNull String mainCommandAlias, @NotNull String alias, @NotNull String... args) { if(playerOnly && !(sender instanceof Player)) { messageNotFromConsole.send(sender); } else if(getPermission() != null && !sender.hasPermission(getPermission())) { messageNoPermission.send(sender); } else { return tabComplete(sender, mainCommandAlias, alias, args); } return null; } /** * Gets the help for a given {@link CommandSender}. * * @param requester The {@link CommandSender} that requested help. * @return All the help data for this command. */ @Override public @Nullable List getHelp(@NotNull CommandSender requester) { List help = new ArrayList<>(1); help.add(new HelpData(getTranslatedName(), null, getDescription())); return help; } /** * Shows the help to a given command sender. * * @param sendTo The command sender that requested help. * @param usedMainCommandAlias The used backpack alias to replace the /backpack with the used alias. */ @Override public void showHelp(final @NotNull CommandSender sendTo, final @NotNull String usedMainCommandAlias) { try { showHelp.invoke(minepacksCommandManager, sendTo, usedMainCommandAlias, doGetHelp(sendTo)); } catch(Exception e) { plugin.getLogger().log(Level.SEVERE, e, () -> "Failed to show help for command " + usedMainCommandAlias); } } /** * Checks if a user can use the command. Checks permission, marriage status and player/console. * * @param sender The player/console that should be checked. * @return True if it can use the command, false if not. */ @Override public boolean canUse(@NotNull CommandSender sender) { return (!playerOnly || sender instanceof Player) && (getPermission() == null || sender.hasPermission(getPermission())); } //endregion } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/MinepacksCommandManager.java ================================================ /* * Copyright (C) 2019 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; import org.jetbrains.annotations.NotNull; @SuppressWarnings("unused") public interface MinepacksCommandManager { /** * Registers a new sub-command for /backpack. * This function is only available if the plugin is not running in standalone mode! * * @param command The command that should be registered. */ void registerSubCommand(@NotNull MinepacksCommand command); /** * Unregisters a sub-command for /backpack. * This function is only available if the plugin is not running in standalone mode! * * @param command The command that should be unregistered. */ void unRegisterSubCommand(@NotNull MinepacksCommand command); } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/MinepacksPlugin.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @SuppressWarnings("unused") public interface MinepacksPlugin { /** * Gets the instance of the minepacks plugin. * WARNING use this function at your own risk! If the plugin is not installed the MinepacksPlugin class will be unknown! * * @return The instance of the minepacks plugin. */ static @Nullable MinepacksPlugin getInstance() { Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin("Minepacks"); return (plugin instanceof MinepacksPlugin && plugin.isEnabled()) ? (MinepacksPlugin) plugin : null; } /** * Checks if the plugin is running in standalone mode. Some features and API functions are not available in standalone mode! * * @return True if the plugin is running in standalone mode. */ boolean isRunningInStandaloneMode(); /** * Let a given player open the backpack of an other player. * * @param opener The player who opens the backpack. * @param owner The owner of the backpack that should be opened. * @param editable Defines if the player who has opened the backpack can change the items inside. */ void openBackpack(@NotNull final Player opener, @NotNull final OfflinePlayer owner, final boolean editable); /** * Let a given player open a given {@link Backpack}. * * @param opener The player who opens the backpack. * @param backpack The backpack to be opened. null will result in an error message for the player. * @param editable Defines if the player who has opened the backpack can change the items inside. */ void openBackpack(@NotNull final Player opener, @Nullable final Backpack backpack, boolean editable); /** * Let a given player open the backpack of an other player. * * @param opener The player who opens the backpack. * @param owner The owner of the backpack that should be opened. * @param editable Defines if the player who has opened the backpack can change the items inside. * @param title Custom title for the backpack (will be shown to the player who opened the backpack. */ void openBackpack(@NotNull final Player opener, @NotNull final OfflinePlayer owner, final boolean editable, @Nullable String title); /** * Let a given player open a given {@link Backpack}. * * @param opener The player who opens the backpack. * @param backpack The backpack to be opened. null will result in an error message for the player. * @param editable Defines if the player who has opened the backpack can change the items inside. * @param title Custom title for the backpack (will be shown to the player who opened the backpack. */ void openBackpack(@NotNull final Player opener, @Nullable final Backpack backpack, boolean editable, @Nullable String title); /** * Retrieves the backpack for a given player. * This method only returns a backpack if it is in the cache. * * @param owner The player who's backpack should be retrieved. * @return The backpack of the given player. null if the backpack is in the cache. */ @Nullable Backpack getBackpackCachedOnly(@NotNull final OfflinePlayer owner); /** * Retrieves the backpack for a given player. * This method runs async! The result will be delivered with a callback. * If no backpack exists a new one will be created. * * @param owner The player who's backpack should be retrieved. * @param callback The callback delivering the result of the request. */ void getBackpack(@NotNull final OfflinePlayer owner, @NotNull final Callback callback); /** * Retrieves the backpack for a given player. * This method runs async! The result will be delivered with a callback. * * @param owner The player who's backpack should be retrieved. * @param callback The callback delivering the result of the request. * @param createNewIfNotExists If set to true, a new backpack will be created if there currently is no backpack for this player. */ void getBackpack(@NotNull final OfflinePlayer owner, @NotNull final Callback callback, boolean createNewIfNotExists); /** * Gets the command manager of the Minepacks plugin. * * @return The command manager instance. null if the plugin is running in standalone mode */ @Nullable MinepacksCommandManager getCommandManager(); /** * Checks if the player is allowed to open a backpack based on is permissions and current game-mode. * * @param player The player to be checked. * @return True if the player can use a backpack. False if not. */ boolean isPlayerGameModeAllowed(final @NotNull Player player); /** * Gets the item filter. * * @return The item filter. Null if item filter is disabled */ @Nullable ItemFilter getItemFilter(); /** * Checks if an item is a backpack shortcut item. * * @param itemStack item to check. * @return true if the item is a backpack shortcut item, false if not. */ boolean isBackpackItem(final @Nullable ItemStack itemStack); /** * Checks if a player can use the backpack at its current location (or if the world is disabled in the config). * Does not check if the player has the permission to use the backpack!!! * * @param player The player that should be checked. * @return The configured reason why the player can not access at its current location. {@link WorldBlacklistMode#None} if the player can use the backpack. */ @NotNull WorldBlacklistMode isDisabled(Player player); } ================================================ FILE: Minepacks-API/src/at/pcgamingfreaks/Minepacks/Bukkit/API/WorldBlacklistMode.java ================================================ /* * Copyright (C) 2020 GeorgH93 * * 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 * (at your option) 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 . */ package at.pcgamingfreaks.Minepacks.Bukkit.API; public enum WorldBlacklistMode { Message, MissingPermission, NoPlugin, None } ================================================ FILE: README.md ================================================ [banner]: https://pcgamingfreaks.at/images/minepacks.png [spigot]: https://www.spigotmc.org/resources/19286/ [spigotRatingImg]: https://img.shields.io/badge/dynamic/json.svg?color=brightgreen&label=rating&query=%24.rating.average&suffix=%20%2F%205&url=https%3A%2F%2Fapi.spiget.org%2Fv2%2Fresources%2F19286 [spigotDownloadsImg]: https://img.shields.io/badge/dynamic/json.svg?color=brightgreen&label=downloads%20%28spigotmc.org%29&query=%24.downloads&url=https%3A%2F%2Fapi.spiget.org%2Fv2%2Fresources%2F19286 [bukkit]: https://dev.bukkit.org/projects/minepacks [bukkitDownloadsImg]: https://cf.way2muchnoise.eu/full_minepacks_downloads.svg [versionsImg]: https://cf.way2muchnoise.eu/versions/minepacks.svg [issues]: https://github.com/GeorgH93/Minepacks/issues [wiki]: https://github.com/GeorgH93/Minepacks/wiki [wikiFAQ]: https://github.com/GeorgH93/Minepacks/wiki/FAQ [wikiPermissions]: https://github.com/GeorgH93/Minepacks/wiki/Permissions [release]: https://github.com/GeorgH93/Minepacks/releases/latest [releaseImg]: https://img.shields.io/github/release/GeorgH93/Minepacks.svg?label=github%20release [license]: https://github.com/GeorgH93/Minepacks/blob/master/LICENSE [licenseImg]: https://img.shields.io/github/license/GeorgH93/Minepacks.svg [ci]: https://ci.pcgamingfreaks.at/job/Minepacks/ [ciImg]: https://ci.pcgamingfreaks.at/job/Minepacks/badge/icon [ciDev]: https://ci.pcgamingfreaks.at/job/Minepacks%20Dev/ [ciDevImg]: https://ci.pcgamingfreaks.at/job/Minepacks%20Dev/badge/icon [apiVersionImg]: https://img.shields.io/badge/dynamic/xml.svg?label=api-version&query=%2F%2Frelease[1]&url=https%3A%2F%2Frepo.pcgamingfreaks.at%2Frepository%2Fmaven-releases%2Fat%2Fpcgamingfreaks%2FMinepacks-API%2Fmaven-metadata.xml [api]: https://github.com/GeorgH93/Minepacks/tree/master/Minepacks-API [apiJavaDoc]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/javadoc/ [apiBuilds]: https://ci.pcgamingfreaks.at/job/Minepacks%20API/ [bugReports]: https://github.com/GeorgH93/Minepacks/issues?q=is%3Aissue+is%3Aopen+label%3Abug [bugReportsImg]: https://img.shields.io/github/issues/GeorgH93/Minepacks/bug.svg?label=bug%20reports [reportBug]: https://github.com/GeorgH93/Minepacks/issues/new?labels=bug&template=bug.md [featureRequests]: https://github.com/GeorgH93/Minepacks/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement [featureRequestsImg]: https://img.shields.io/github/issues/GeorgH93/Minepacks/enhancement.svg?label=feature%20requests&color=informational [requestFeature]: https://github.com/GeorgH93/Minepacks/issues/new?labels=enhancement&template=feature.md [config]: https://github.com/GeorgH93/Minepacks/blob/master/Minepacks/resources/config.yml [pcgfPluginLib]: https://github.com/GeorgH93/PCGF_PluginLib [pcgfPluginLibAdvantages]: https://github.com/GeorgH93/Minepacks/wiki/Build-and-Mode-comparison#Advantages-of-using-the-PCGF-PluginLib [languages]: https://github.com/GeorgH93/Minepacks/tree/master/Minepacks/resources/lang [![Logo][banner]][spigot] Minepacks is a free and reliable backpack plugin for minecraft server running bukkit or spigot. [![ciImg]][ci] [![releaseImg]][release] [![apiVersionImg]][api] [![licenseImg]][license] [![spigotRatingImg]][spigot] [![featureRequestsImg]][featureRequests] [![bugReportsImg]][bugReports] [![spigotDownloadsImg]][spigot] [![bukkitDownloadsImg]][bukkit] ## Features: * [Configuration][config] * Backpack size controlled by [permissions][wikiPermissions] * Auto item-collect on full inventory (can be enabled in the config) * Multiple storage back-ends (Files, SQLite, MySQL) * Multi language support ([multiple language file included][languages]) * Item filter (block items from being stored in the backpack) * Preserves the NBT data of items (everything that can be stored in a chest can be stored in the backpack) * Support for name changing / UUIDs * Auto-updater * [API][api] for developers ## Requirements: ### Runtime requirements: * Java 8 * Bukkit, Spigot or Paper for Minecraft 1.8 or newer ![versionsImg] * (Optional) [PCGF PluginLib][pcgfPluginLib] ([Advantages of using the PCGF PluginLib][pcgfPluginLibAdvantages]) ### Build requirements: * JDK for Java 8 * Maven 3 * git ## Build from source: The plugin can be build in 3 different configurations. All the details about the different build configs and runtime modes can be found [here](https://github.com/GeorgH93/Minepacks/wiki/Build-and-Mode-comparison). ### Normal version: ``` git clone https://github.com/GeorgH93/Minepacks.git cd Minepacks mvn package ``` The final file will be in the `Minepacks/target` folder, named `Minepacks-.jar`. ### Standalone version: This version works without the PCGF-PluginLib, however some API features are not available. ``` git clone https://github.com/GeorgH93/Minepacks.git cd Minepacks mvn package -P Standalone ``` The final file will be in the `Minepacks/target` folder, named `Minepacks--Standalone.jar`. ### Release version: This is the version of the plugin published on dev.bukkit.org and spigotmc.org. ``` git clone https://github.com/GeorgH93/Minepacks.git cd Minepacks mvn clean install -P Standalone mvn clean package -P Release ``` The final file will be in the `Minepacks/target` folder, named `Minepacks--Release.jar`. ## API: Minepacks V2 comes with an API that allows you to interact with this plugin. If you think there is something missing in the API feel free to open a [feature request][requestFeature]. Please do not access data of the plugin in any other way than through the provided API, the inner workings will change and I won't keep track of what you are using in your plugin. For more details about the API please check the following links: [Source Code & Details][api] ⚫ [JavaDoc][apiJavaDoc] ⚫ [Build Server][apiBuilds] ## Support: * [Wiki][wiki] * [Issue tracker][issues] * [new feature request][requestFeature] * [new bug report][reportBug] * [Faq][wikiFAQ] ## Links: * [Spigot][spigot] - [![spigotDownloadsImg]][spigot] * [CurseForge][bukkit] - [![bukkitDownloadsImg]][bukkit] * [Build Server - Release Builds ![ciImg]][ci] * [Build Server - Dev Builds ![ciDevImg]][ciDev] ================================================ FILE: pom.xml ================================================ 4.0.0 at.pcgamingfreaks Minepacks-Parent ${revision} pom 2.5.7 UTF-8 UTF-8 35 21 1.0.40.7-SNAPSHOT 1.15.2-R0.1-SNAPSHOT 3.6.2 1.18.42 GeorgH93 yyyyMMddHHmmss ${maven.build.timestamp} ${project.version}-T${timestamp} georgh93 https://sonarcloud.io scm:git:git@github.com:GeorgH93/Minepacks.git scm:git:git@github.com:GeorgH93/Minepacks.git git@github.com:GeorgH93/Minepacks.git GitHub https://github.com/GeorgH93/Minepacks/issues jenkins https://ci.pcgamingfreaks.at/job/Minepacks/ Minepacks-Parent Minepacks is a backpack plugin with different backpack sizes, multi-language support and SQLite and MySQL storage support. https://www.spigotmc.org/resources/19286/ 2014 GNU General Public License (GPL) v3 https://www.gnu.org/licenses/gpl-3.0.txt repo pcgf-repo https://repo.pcgamingfreaks.at/repository/maven-everything/ spigot-nexus https://hub.spigotmc.org/nexus/content/groups/public/ org.jetbrains annotations 23.1.0 org.bukkit bukkit ${bukkitVersion} provided org.projectlombok lombok ${lombok.version} provided clean package src maven-compiler-plugin 3.8.1 1.8 1.8 UTF-8 org.projectlombok lombok ${lombok.version} org.projectlombok lombok-maven-plugin 1.18.10.0 generate-sources delombok org.codehaus.mojo flatten-maven-plugin 1.2.1 true flatten process-resources flatten flatten.clean clean clean Minepacks-API Components/Minepacks-MagicValues Minepacks Release false Components/Minepacks-BadRabbit-Bukkit Components/Minepacks-Bootstrap-Paper releases https://repo.pcgamingfreaks.at/repository/maven-releases/ snapshots https://repo.pcgamingfreaks.at/repository/maven-snapshots/