diff --git a/.github/workflows/CI-Test.yaml b/.github/workflows/CI-Test.yaml new file mode 100644 index 0000000..901543a --- /dev/null +++ b/.github/workflows/CI-Test.yaml @@ -0,0 +1,30 @@ +name: CI Test + +on: + push: + branches: [ dev ] + pull_request: + branches: [ master, dev ] + +jobs: + check: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Gradle build task + run: ./gradlew check + +# - name: Upload artifact +# uses: actions/upload-artifact@v2 +# with: +# name: Archive +# path: build/libs/actions-test-1.0-SNAPSHOT.jar +# diff --git a/.github/workflows/do-release.yaml b/.github/workflows/do-release.yaml new file mode 100644 index 0000000..ef5cde3 --- /dev/null +++ b/.github/workflows/do-release.yaml @@ -0,0 +1,48 @@ +# This work flow will build project with Gradle wrapper, +# create a release, and upload contents of ./build/libs/ +# to the release. +name: Create or update release + +on: + push: + branches: + - 'release/**' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Get version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF#refs/heads/release/} + + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Gradle build task + run: ./gradlew build + + - name: Create release, update, and upload assets + uses: meeDamian/github-release@v2.0.1 + with: + tag: ${{ steps.get_version.outputs.VERSION }} + token: ${{ secrets.GITHUB_TOKEN }} + prerelease: true + draft: true + allow_override: true + body: | + Changelog for ${{ steps.get_version.outputs.VERSION }} : + * Change Materials to match Minecraft 1.15 + * Integrated code from local API + * Add workflows for issue and release creation. + * Refactored main class + * Change how plugin watches for eggs to hatch + * Change ProjectileHitEvent: getBlock location -> getEnttity location + * Changed Config library to Lightning Storage + files: build/libs/* + gzip: folders diff --git a/.github/workflows/todo-issue.yaml b/.github/workflows/todo-issue.yaml new file mode 100644 index 0000000..a856fe0 --- /dev/null +++ b/.github/workflows/todo-issue.yaml @@ -0,0 +1,31 @@ +name: "Manage TODO <-> Issue" +on: ["push"] +jobs: + yaml-to-list: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@master" + - name: "TODO to Issue for YAML / Python" + uses: "alstr/todo-to-issue-action@master" + with: + REPO: ${{ github.repository }} + BEFORE: ${{ github.event.before }} + SHA: ${{ github.sha }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + LABEL: "# TODO" + COMMENT_MARKER: "#" + id: "todo" + java-to-list: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@master" + - name: "TODO to Issue for Java" + uses: "alstr/todo-to-issue-action@master" + with: + REPO: ${{ github.repository }} + BEFORE: ${{ github.event.before }} + SHA: ${{ github.sha }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + LABEL: "// TODO" + COMMENT_MARKER: "//" + id: "todo" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..668117c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +[Full Changelog](http://link.to/commit/history) + +### v1.2.3 (*Unreleased*) + + +* Change Materials to work with Minecraft 1.15 +* Change how plugin listens for eggs to hatch +* Change hatch location to prevent suffocation +* Add a changelog + + + diff --git a/MethodTest/.idea/artifacts/MethodTest_jar.xml b/MethodTest/.idea/artifacts/MethodTest_jar.xml deleted file mode 100644 index fb455c6..0000000 --- a/MethodTest/.idea/artifacts/MethodTest_jar.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts - - - - - \ No newline at end of file diff --git a/MethodTest/.idea/vcs.xml b/MethodTest/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/MethodTest/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index bb860bf..376e69b 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # BreedablePetsMC -Breed parrots and polar bears. Customize the food/item you use to tame each mob. +Breed animals that are not normally breed-able in Minecraft. -**Breedable Pets** is a [Minecraft](http://minecraft.net) server plugin for [Bukkit](http://http://bukkit.org) / [Spigot](http://spigotmc.org) / [Paper](http://papermc.io) that allows you to breed animals that are not usually breedable. + + +**Breedable Pets** is a [Minecraft](http://minecraft.net) server plugin for [Bukkit](http://http://bukkit.org) / [Spigot](http://spigotmc.org) / [Paper](http://papermc.io) that allows you to breed animals that are not usually breed-able. ### Installation -Drop the jar in your plugins folder and start the server. +Download jar from the [releases](https://github.com/Magnum97/BreedablePetsMC/releases) page and put it in your server's `plugins/` folder, then start the server. +Optionally you can compile it yourself. ## Usage There is only one command, `/breedablepets` alias `/bp`. Sub commands are: @@ -15,7 +18,7 @@ There is only one command, `/breedablepets` alias `/bp`. Sub commands are: For settings see [config.yml](https://github.com/Magnum97/BreedablePetsMC/blob/master/src/main/resources/config.yml)\ I tried to put all options in there. Some are not implemented yet. \ -Currently only parrots are breedable. You must feed them seeds *other* than wheat. Wheat seeds are still used for taming wild parrots. Foods are hard coded but plan to move to config in a future version. +Currently only parrots are breed-able. You must feed them seeds *other* than wheat. Wheat seeds are still used for taming wild parrots. Foods are hard coded but plan to move to config in a future version. ### Contributing This is a pretty basic plugin. If you have any thoughts, good or bad, I would like them or any suggestions for features or improvements.\ diff --git a/build.gradle b/build.gradle index af2cc47..7dd2815 100644 --- a/build.gradle +++ b/build.gradle @@ -6,21 +6,22 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocatio plugins { id 'java' + id 'application' id 'kr.entree.spigradle' version '1.2.4' id "io.freefair.lombok" version "5.0.0-rc2" id 'com.github.johnrengelman.shadow' version '5.1.0' } -group= 'me.magnum' // Put your groupId here -version= '1.3.1a' // Put your version here +group = 'me.magnum' // Put your groupId here +version = '2.0.0-SNAPSHOT' // Put your version here archivesBaseName = 'BreedablePets' // Put your artifactId here -mainClassName = 'me.magnum.breedablepets.Main' +mainClassName = 'me.magnum.Breedable' targetCompatibility = 1.8 sourceCompatibility = 1.8 // See https://github.com/EntryPointKR/Spigradle#repositories for repository shortcodes repositories { - mavenLocal() +// mavenLocal() mavenCentral() paper() enderZone() @@ -29,14 +30,16 @@ repositories { } dependencies { - spigot() - paper() + compileOnly spigot('1.15.2') implementation 'fr.mrmicky:FastParticles:1.2.0' - implementation 'com.github.JavaFactoryDev:LightningStorage:3.0.3' +// implementation files ('/home/rich/.m2/repository/com/github/javafactorydev/lightningstorage/3.1.1-SNAPSHOT/lightningstorage-3.1.1-SNAPSHOT.jar') + implementation 'com.github.Magnum97:LightningStorage:frame-header-SNAPSHOT' +// implementation 'com.github.JavaFactoryDev:LightningStorage:3.1.1-SNAPSHOT' implementation "co.aikar:acf-bukkit:0.5.0-SNAPSHOT" - implementation 'com.github.kangarko:Foundation:5.1.8@jar' // Kangerko's Foundation library +// implementation 'com.github.kangarko:Foundation:5.3.8@jar' // Kangerko's Foundation library } +defaultTasks 'clean', 'build' compileJava { options.compilerArgs += ["-parameters"] options.fork = true @@ -47,6 +50,7 @@ task relocateShadowJar(type: ConfigureShadowRelocation) { prefix = "shadow" // Default value is "shadow" } +tasks.shadowJar.dependsOn tasks.relocateShadowJar shadowJar { classifier = null // remove -all from end of jar } @@ -56,23 +60,23 @@ spigot { apiVersion = '1.15' load = STARTUP commands { - give { - aliases = ['i'] - description = 'Give command.' - permission = 'test.foo' - permissionMessage = 'You do not have permission!' - usage = '/ [test|stop]' + breedablepets { + aliases = ['bp'] + description = 'Main command for BreedablePets' + permission = 'breedablepets.command' + permissionMessage = 'You do not have permission: breedablepets.command' + usage = '/ [ help | parrotegg [fertile]]' } } permissions { - 'test.foo' { - description = 'Allows foo command' - defaults = 'true' + 'breedablepets.command' { + description = 'Allows main command' + defaults = 'op' } - 'test.*' { + 'breedablepets.*' { description = 'Wildcard permission' defaults = 'op' - children = ['test.foo': true] + children = ['breedablepets.command': true, 'breedablepets.command.parrot': true, 'breedabpepets.reload': true] } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf..490fda8 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f4d7b2b..a4b4429 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index b0d6d0a..2fe81a7 --- a/gradlew +++ b/gradlew @@ -7,7 +7,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -125,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -154,19 +154,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -175,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9991c50..62bd9b9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -5,7 +5,7 @@ @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem -@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..6aa51d7 --- /dev/null +++ b/lombok.config @@ -0,0 +1,2 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true diff --git a/src/main/java/me/magnum/breedablepets/Main.java b/src/main/java/me/magnum/Breedable.java similarity index 50% rename from src/main/java/me/magnum/breedablepets/Main.java rename to src/main/java/me/magnum/Breedable.java index 8608a08..d33793e 100644 --- a/src/main/java/me/magnum/breedablepets/Main.java +++ b/src/main/java/me/magnum/Breedable.java @@ -23,64 +23,80 @@ * USA * */ -package me.magnum.breedablepets; +package me.magnum; import co.aikar.commands.BukkitCommandManager; +import de.leonhard.storage.Yaml; +import de.leonhard.storage.sections.FlatFileSection; +import lombok.Getter; +import me.magnum.breedablepets.Command; import me.magnum.breedablepets.listeners.BreedListener; -import me.magnum.breedablepets.listeners.MyListener; -import me.magnum.breedablepets.util.Config; -import me.magnum.lib.Common; -import me.magnum.lib.SimpleConfig; +import me.magnum.breedablepets.listeners.EggListener; +import me.magnum.breedablepets.util.Common; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.EntityType; import org.bukkit.plugin.java.JavaPlugin; +public class Breedable extends JavaPlugin { + + @Getter + private static Breedable plugin; + // @Getter +// private SimpleConfig cfg; + @Getter + private Yaml cfg; -public class Main extends JavaPlugin { - - - public static Main plugin; - public static SimpleConfig cfg; - @Override public void onEnable () { plugin = this; - Common.setInstance(plugin); - Common.log("Loading breed-able pets..."); - cfg = new SimpleConfig("config.yml", plugin); - Config.init(); - // Remain.setPlugin(plugin); //todo Add compatability - plugin.getServer().getPluginManager().registerEvents(new MyListener(), plugin); - plugin.getServer().getPluginManager().registerEvents(new BreedListener(), plugin); + setupConfig(); +// Remain.setPlugin(plugin); // TODO Add backwards compatibility + plugin.getServer().getPluginManager().registerEvents(new EggListener(), this); + plugin.getServer().getPluginManager().registerEvents(new BreedListener(), this); registerCommands(); } - - @SuppressWarnings("deprecation") + + private void setupConfig () { + cfg = new Yaml("settings.yml", getDataFolder().toString(), getResource("settings.yml")); + String[] header = {"Config file for BreedablePets", + "by Magnum1997", + "This should be self-explanatory. I tried to comment settings.", + "For problems, questions, or feedback please visit", + "https://github.com/Magnum97/BreedablePetsMC/issues"}; + cfg.framedHeader(header); + // Set defaults + cfg.setDefault("parrots.hatch-chance", 10); + cfg.setDefault("parrot.egg-chance", 25); + cfg.setDefault("paired-egg-chance", 20); + cfg.setDefault("fertile-egg-chance", 30); + cfg.setDefault("hatch-chance", 10); + cfg.setDefault("rare-chance", 1); + FlatFileSection modifiers = cfg.getSection("modifiers"); + modifiers.setDefault("wheat", 10); + modifiers.setDefault("beetroot", 20); + modifiers.setDefault("pumpkin", 30); + modifiers.setDefault("melon", 30); + modifiers.setDefault("glistering-melon", 100); + } + + @SuppressWarnings ("deprecation") private void registerCommands () { BukkitCommandManager commandManager = new BukkitCommandManager(plugin); - commandManager.registerCommand(new me.magnum.breedablepets.Command()); + commandManager.registerCommand(new Command()); commandManager.enableUnstableAPI("help"); } - - + + @Override public void onDisable () { - Common.setInstance(plugin); - Common.log("Disabling Breedable pets."); + Common.log("Disabling Breed-able pets."); // Remain.setPlugin(null); + // cfg.saveConfig(); cfg = null; plugin = null; } - - public Main getPlugin () { - return plugin; - } - - public SimpleConfig getCfg () { - return cfg; - } - + public void spawnMob (World world, Location location, EntityType mobType) { world.spawnEntity(location, mobType); } diff --git a/src/main/java/me/magnum/breedablepets/Command.java b/src/main/java/me/magnum/breedablepets/Command.java index 437bd41..c5e3c8d 100644 --- a/src/main/java/me/magnum/breedablepets/Command.java +++ b/src/main/java/me/magnum/breedablepets/Command.java @@ -28,13 +28,16 @@ import co.aikar.commands.BaseCommand; import co.aikar.commands.CommandHelp; import co.aikar.commands.annotation.*; +import me.magnum.Breedable; +import me.magnum.breedablepets.util.CheckSender; import me.magnum.breedablepets.util.ItemUtil; import me.magnum.breedablepets.util.SpawnPets; -import me.magnum.lib.CheckSender; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -@CommandAlias("breedablepet|bp") +// TODO refine permissions +// ie. breedable.command breedable.command.parrot breedable.command.reload +@CommandAlias("breedablepets|bp") public class Command extends BaseCommand { @HelpCommand @@ -44,12 +47,12 @@ public void onHelp (CommandSender sender, CommandHelp help) { @Subcommand("parrotegg") @Description("Get a parrot egg") - @CommandPermission("breedable.parrot.egg") + @CommandPermission("breedablepets.command.parrotegg") public void onCommand (CommandSender sender, @Default("false") String fertile) { ItemUtil util = new ItemUtil(); Player p = (Player) sender; - if (!CheckSender.isPlayer(sender)) { + if (! CheckSender.isPlayer(sender)) { return; } if ((fertile.equalsIgnoreCase("fertile"))&& sender.hasPermission("breedable.parrot.fertile")) { @@ -62,7 +65,7 @@ public void onCommand (CommandSender sender, @Default("false") String fertile) { @Subcommand("reload") @CommandPermission("breedable.reload") public void onReload (CommandSender sender) { - Main.cfg.reloadConfig(); + Breedable.getPlugin().getCfg().forceReload(); } @CommandAlias("sp") diff --git a/src/main/java/me/magnum/breedablepets/listeners/BreedListener.java b/src/main/java/me/magnum/breedablepets/listeners/BreedListener.java index 2782127..db011c2 100644 --- a/src/main/java/me/magnum/breedablepets/listeners/BreedListener.java +++ b/src/main/java/me/magnum/breedablepets/listeners/BreedListener.java @@ -27,10 +27,8 @@ import fr.mrmicky.fastparticle.FastParticle; import fr.mrmicky.fastparticle.ParticleType; -import me.magnum.breedablepets.Main; -import me.magnum.breedablepets.util.Config; +import me.magnum.Breedable; import me.magnum.breedablepets.util.ItemUtil; -import me.magnum.lib.SimpleConfig; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -46,14 +44,14 @@ import java.util.concurrent.ThreadLocalRandom; public class BreedListener implements Listener { - + private final ItemUtil items = new ItemUtil(); - private final SimpleConfig cfg = Main.cfg; - + // private final SimpleConfig cfg = Main.getCfg(); + public BreedListener () { } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + + @EventHandler (priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onFeed (PlayerInteractEntityEvent pie) { Player player = pie.getPlayer(); Entity target = pie.getRightClicked(); @@ -63,7 +61,7 @@ public void onFeed (PlayerInteractEntityEvent pie) { } Tameable tamed = (Tameable) target; Sittable sitting = (Sittable) target; - if ((!tamed.isTamed()) || (!sitting.isSitting())) { + if ((! tamed.isTamed()) || (! sitting.isSitting())) { return; } int chanceModifier; @@ -71,11 +69,11 @@ public void onFeed (PlayerInteractEntityEvent pie) { return; } if (Arrays.asList(Material.BEETROOT_SEEDS, - Material.MELON_SEEDS, - Material.MELON, - Material.PUMPKIN_SEEDS, - Material.SPECKLED_MELON).contains(hand)) { - chanceModifier = foodCalc(target, hand); // todo increase chance of egg/fertile egg by type of food. + Material.MELON_SEEDS, + Material.MELON, + Material.PUMPKIN_SEEDS, + Material.GLISTERING_MELON_SLICE).contains(hand)) { + chanceModifier = foodCalc(target, hand); // TODO increase chance of egg/fertile egg by type of food. } else { return; @@ -83,16 +81,16 @@ public void onFeed (PlayerInteractEntityEvent pie) { pie.setCancelled(true); sitting.setSitting(true); player.getInventory().getItemInMainHand().setAmount(player.getInventory().getItemInMainHand().getAmount() - 1); - - // Common.tell(player, "Base chance of egg: " + chanceModifier); // todo remove before deploy - + + // Common.tell(player, "Base chance of egg: " + chanceModifier); // TODO remove before deploy + List nearby = target.getNearbyEntities(5, 2, 5); - + World w = player.getWorld(); Location loc = target.getLocation(); Entity mate = null; boolean hasMate = false; - + for (Entity entity : nearby) { if (entity.getType() == target.getType()) { hasMate = true; @@ -100,7 +98,7 @@ public void onFeed (PlayerInteractEntityEvent pie) { } } -/* todo find nearest parrot +/* // TODO find nearest parrot for (int i = 0; i < nearby.size(); i++) { if (nearby.get(i).getType().equals(EntityType.PARROT)){ hasMate=true; @@ -109,22 +107,22 @@ public void onFeed (PlayerInteractEntityEvent pie) { } } */ - + // int random = new Random().nextInt(100); double x = target.getLocation().getX(); double y = target.getLocation().getY() + 1; double z = target.getLocation().getZ(); if (hasMate) { - if (ThreadLocalRandom.current().nextInt(100) < Config.fertileChance ) { + if (ThreadLocalRandom.current().nextInt(100) < (Breedable.getPlugin().getCfg().getInt("fertile-egg-chance"))) { w.dropItemNaturally(loc, items.regEgg.clone()); - // w.dropItemNaturally(loc, items.fertileEgg.clone()); // todo To be fertile egg - disabled until single throw bug fixed + // w.dropItemNaturally(loc, items.fertileEgg.clone()); // TODO To be fertile egg - disabled until single throw bug fixed FastParticle.spawnParticle(target.getWorld(), ParticleType.HEART, target.getLocation(), 3); FastParticle.spawnParticle(target.getWorld(), ParticleType.HEART, x, y, z, 3); FastParticle.spawnParticle(w, ParticleType.HEART, mate.getLocation(), 3); FastParticle.spawnParticle(w, ParticleType.HEART, x, y, z, 3); } else { - if (ThreadLocalRandom.current().nextInt(1, 101) < Config.eggChance ) { + if (ThreadLocalRandom.current().nextInt(1, 101) < Breedable.getPlugin().getCfg().getInt("egg-chance")) { w.dropItemNaturally(loc, items.regEgg.clone()); FastParticle.spawnParticle(target.getWorld(), ParticleType.HEART, target.getLocation(), 3); FastParticle.spawnParticle(target.getWorld(), ParticleType.HEART, x, y, z, 3); @@ -132,36 +130,37 @@ public void onFeed (PlayerInteractEntityEvent pie) { FastParticle.spawnParticle(w, ParticleType.HEART, x, y, z, 3); } } - + } else { - if (ThreadLocalRandom.current().nextInt(100) < Config.eggChance) { + if (ThreadLocalRandom.current().nextInt(100) < Breedable.getPlugin().getCfg().getInt("egg-change")) { FastParticle.spawnParticle(w, ParticleType.NOTE, target.getLocation(), 3, x, y, z); // FastParticle.spawnParticle(w, ParticleType.NOTE, x, y, z, 1); w.dropItemNaturally(loc, items.regEgg.clone()); } } - + } - - // todo get length of configuration section and make array of item/chance pairs. + + // TODO get length of configuration section and make array of item/chance pairs. private Integer foodCalc (Entity target, Material type) { int chance = 0; switch (type) { - case SEEDS: - chance = cfg.getInt("modifier.wheat"); + case WHEAT_SEEDS: + chance = Breedable.getPlugin().getCfg().getInt("modifier.wheat"); break; case BEETROOT_SEEDS: - chance = cfg.getInt("modifier.beetroot"); + chance = Breedable.getPlugin().getCfg().getInt("modifier.beetroot"); break; case PUMPKIN_SEEDS: - chance = cfg.getInt("modifier.pumpkin"); + chance = Breedable.getPlugin().getCfg().getInt("modifier.pumpkin"); break; case MELON_SEEDS: - chance = cfg.getInt("modifier.melon"); + chance = Breedable.getPlugin().getCfg().getInt("modifier.melon"); break; - case SPECKLED_MELON: - chance = cfg.getInt("modifier.glistering"); + case GLISTERING_MELON_SLICE: + _MELON: + chance = Breedable.getPlugin().getCfg().getInt("modifier.glistering"); break; } return chance; diff --git a/src/main/java/me/magnum/breedablepets/listeners/MyListener.java b/src/main/java/me/magnum/breedablepets/listeners/EggListener.java similarity index 57% rename from src/main/java/me/magnum/breedablepets/listeners/MyListener.java rename to src/main/java/me/magnum/breedablepets/listeners/EggListener.java index 1e247c3..9897f1b 100644 --- a/src/main/java/me/magnum/breedablepets/listeners/MyListener.java +++ b/src/main/java/me/magnum/breedablepets/listeners/EggListener.java @@ -25,43 +25,69 @@ */ package me.magnum.breedablepets.listeners; -import me.magnum.breedablepets.Main; -import me.magnum.breedablepets.util.Config; +import me.magnum.Breedable; +import me.magnum.breedablepets.util.Common; import me.magnum.breedablepets.util.ItemUtil; import me.magnum.breedablepets.util.SpawnPets; -import me.magnum.lib.Common; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Dispenser; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockDispenseEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerEggThrowEvent; import org.bukkit.inventory.ItemStack; +import java.util.HashMap; +import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; -public class MyListener implements Listener { - - private ItemUtil itemsAPI = new ItemUtil(); - - @EventHandler(priority = EventPriority.HIGH) +public class EggListener implements Listener { + + private static final HashMap flyingEggs = new HashMap <>(); + private static final HashMap flyingFertileEggs = new HashMap <>(); + private final ItemUtil itemsAPI = new ItemUtil(); + + @EventHandler (priority = EventPriority.HIGH) public void onEggThrow (PlayerEggThrowEvent e) { + ItemStack hand = e.getPlayer().getInventory().getItemInMainHand(); + if (! hand.isSimilar(itemsAPI.regEgg) || hand.isSimilar(itemsAPI.fertileEgg)) return; + + UUID eggId = e.getEgg().getUniqueId(); + e.setHatching(false); if (e.getPlayer().getInventory().getItemInMainHand().isSimilar(itemsAPI.regEgg)) { - e.setHatching(false); - Common.sendABar(e.getPlayer(), "I really hope it hatches..."); - if (ThreadLocalRandom.current().nextInt(100) < Config.eggChance) { - SpawnPets.newParrot(e.getPlayer(), e.getEgg().getLocation()); - } + Common.sendBar(e.getPlayer(), "I really hope it hatches..."); + flyingEggs.put(eggId, e.getPlayer()); } if (e.getPlayer().getInventory().getItemInMainHand().isSimilar(itemsAPI.fertileEgg)) { - e.setHatching(false); - Common.sendABar(e.getPlayer(), "You try hatching the Parrot egg..."); - SpawnPets.newParrot(e.getPlayer(), e.getEgg().getLocation()); + flyingFertileEggs.put(eggId, e.getPlayer()); + Common.sendBar(e.getPlayer(), "You try hatching the Parrot egg..."); + } + } + + @EventHandler + public void eggHit (ProjectileHitEvent hitEvent) { + UUID projectile = hitEvent.getEntity().getUniqueId(); + Location loc = hitEvent.getEntity().getLocation(); + if (flyingEggs.containsKey(projectile)) { + // handle regular egg + int random = ThreadLocalRandom.current().nextInt(100); + int chance = (int) Breedable.getPlugin().getCfg().get("hatch-chance"); + Breedable.getPlugin().getServer().broadcastMessage("Random: " + random + " Chance: " + chance); + if (random < chance) { + SpawnPets.newParrot(flyingEggs.get(projectile), loc); + } + flyingEggs.remove(projectile); + } + if (flyingFertileEggs.containsKey(projectile)) { + // handle fertile egg + SpawnPets.newParrot(flyingFertileEggs.get(projectile), loc); + flyingFertileEggs.remove(projectile); } } - /* @EventHandler public void onHatch (CreatureSpawnEvent e) { @@ -70,11 +96,10 @@ public void onHatch (CreatureSpawnEvent e) { } } */ - + @EventHandler public void onDispenseEgg (BlockDispenseEvent e) { - // todo add config option here - Common.setInstance(Main.plugin); + // TODO add config option here if ((e.getItem() != null) && (e.getItem().getType() != Material.AIR)) { if (e.getItem().getType() == Material.EGG) { Dispenser dispenser = (Dispenser) e.getBlock().getState(); diff --git a/src/main/java/me/magnum/breedablepets/util/CheckSender.java b/src/main/java/me/magnum/breedablepets/util/CheckSender.java new file mode 100755 index 0000000..3e675d0 --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/CheckSender.java @@ -0,0 +1,26 @@ +package me.magnum.breedablepets.util; + +import org.bukkit.block.CommandBlock; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +public class CheckSender { + + + public static boolean isPlayer(CommandSender sender) { + return (sender instanceof Player); + } + + public static boolean isConsole(CommandSender sender) { + return (sender instanceof ConsoleCommandSender); + } + + public static boolean isCommand(CommandSender sender) { + return (sender instanceof CommandBlock); + } + + +} + + diff --git a/src/main/java/me/magnum/breedablepets/util/Common.java b/src/main/java/me/magnum/breedablepets/util/Common.java new file mode 100644 index 0000000..bbdedca --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/Common.java @@ -0,0 +1,83 @@ +package me.magnum.breedablepets.util; + +import me.magnum.Breedable; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +public class Common { + // ------------------------------------------------------------------------------------------------------------ + // Logging and error handling + // ------------------------------------------------------------------------------------------------------------ + + // This is the common library + + + public static void sendTitle(Player pl, String title, String subtitle) { + pl.sendTitle(colorize(title), colorize(subtitle), 20, 3 * 20, 10); + + } + + public static void sendBar(Player pl, String title) { + try { + pl.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(colorize(title))); + + } catch (final Throwable t) { + tell(pl, title); + } + } + + public static void log(String... messages) { + for (final String message : messages) + log(message); + } + + public static void log(String messages) { + tell(Bukkit.getConsoleSender(), "[" + Breedable.getPlugin().getName() + "] " + messages); + } + + public static void tell(CommandSender toWhom, String... messages) { + for (final String message : messages) + tell(toWhom, message); + } + + public static void tell(CommandSender toWhom, String message) { + toWhom.sendMessage(colorize(message)); + } + + public static String colorize(String message) { + return ChatColor.translateAlternateColorCodes('&', message); + } + + public static void registerCommand(Command command) { + try { + final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + commandMapField.setAccessible(true); + + final CommandMap commandMap = (CommandMap) commandMapField.get(Bukkit.getServer()); + commandMap.register(command.getLabel(), command); + + } catch(final Exception e) { + e.printStackTrace(); + } + } + + public static T getOrDefault(T nullable, T def) { + return nullable != null ? nullable : def; + } + + public static void runLater(int delay, BukkitRunnable task) { + runLater(delay, task); + } + + public static void runLater(int delay, Runnable task) { + Bukkit.getScheduler().runTaskLater(Breedable.getPlugin(), task, delay); + } +} diff --git a/src/main/java/me/magnum/breedablepets/util/Config.java b/src/main/java/me/magnum/breedablepets/util/Config.java deleted file mode 100644 index 9eca7cd..0000000 --- a/src/main/java/me/magnum/breedablepets/util/Config.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Breedable PetsMC is a plugin to customize breeding of Minecraft mobs - * Copyright (C) 2019 Richard Simpson - * - * 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 - * - * Contact information: - * Richard Simpson - * 19084 Leaf Lane - * Redding, CA 96003 - * USA - * - */ -package me.magnum.breedablepets.util; - -import lombok.Getter; -import me.magnum.breedablepets.Main; -import me.magnum.lib.Common; -import me.magnum.lib.SimpleConfig; -import org.bukkit.plugin.java.JavaPlugin; - -@Getter -public class Config extends SimpleConfig { - - // public static String version; - public static int eggChance; - public static int pairedChance; - public static int hatchChance; - public static int fertileChance; - public static boolean nameHatchling; - public static String hatchLingName; - public static boolean tamedHatchling; - - private Config (String fileName, JavaPlugin plugin) { - super(fileName, plugin); - setHeader(new String[] { - "--------------------------------------------------------", - " Your configuration file got updated automatically!", - " ", - " Unfortunately, due to how Bukkit saves .yml files,", - " all comments in your file were lost. Please open", - " " + fileName + " from jar to browse the default values.", - "--------------------------------------------------------" - }); - } - - public static void init () { - new Config("config.yml", Main.plugin).onLoad(); - } - - private void onLoad () { - Common.setInstance(Main.plugin); - // version = getString("version"); - eggChance = getInt("egg-chance"); - pairedChance = getInt("paired-egg-chance"); - fertileChance = getInt("fertile-egg-chance"); - nameHatchling = getBoolean("hatches.named"); - hatchLingName = getString("hatches.name"); - tamedHatchling = getBoolean("hatches.tamed"); - - } - -} diff --git a/src/main/java/me/magnum/breedablepets/util/ItemFactory.java b/src/main/java/me/magnum/breedablepets/util/ItemFactory.java new file mode 100644 index 0000000..7483bce --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/ItemFactory.java @@ -0,0 +1,500 @@ +package me.magnum.breedablepets.util; +/* Copyright 2018 Melvin Snijders + * + * Licensed under the MIT License. + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://spdx.org/licenses/MIT.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * ItemFactory - Build your {@link ItemStack} the easy way. (1.13) + * @version 1.0.0 + * @author Melvin Snijders + * @since 20/11/2018 + */ + +public class ItemFactory { + + private final ItemStack itemStack; + private ItemMeta itemMeta; + private List lore = new ArrayList<>(); + + /** + * Construct ItemFactory class with given {@link Material}. + * @param material The {@link Material} for the ItemFactory. + */ + + public ItemFactory(Material material) { + + this.itemStack = new ItemStack(material); + this.itemMeta = this.itemStack.getItemMeta(); + + } + + /** + * Construct ItemFactory class with given {@link Material} and amount. + * @param material The {@link Material} for the ItemFactory. + * @param amount The amount for the ItemFactory. + */ + + public ItemFactory(Material material, int amount) { + + this.itemStack = new ItemStack(material, amount); + this.itemMeta = this.itemStack.getItemMeta(); + + } + + /** + * Construct ItemFactory class with given {@link ItemStack}. + * @param itemStack The {@link ItemStack} for the ItemFactory. + */ + + public ItemFactory(ItemStack itemStack) { + + this.itemStack = itemStack; + this.itemMeta = itemStack.getItemMeta(); + this.lore = this.itemMeta.getLore(); + + } + + /** + * Create a new ItemFactory with a static method (lazy people) + * @param material The {@link Material} for the ItemFactory. + * @return The new ItemFactory instance. + */ + + public static ItemFactory newFactory(Material material) { + + return new ItemFactory(material); + + } + + /** + * Set the {@link ItemMeta} for the ItemStack. + * @param itemMeta The {@link ItemMeta}. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setItemMeta(ItemMeta itemMeta) { + + this.itemMeta = itemMeta; + return this; + + } + + /** + * Set the {@link Material} for the ItemStack. + * @param material The {@link Material}. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setType(Material material) { + + this.itemStack.setType(material); + return this; + + } + + /** + * Set the amount for the ItemStack. + * @param amount The amount. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setAmount(int amount) { + + this.itemStack.setAmount(amount); + return this; + + } + + /** + * Add an {@link Enchantment} to the ItemStack. + * @param enchantment The {@link Enchantment} to add. + * @param level The level of the {@link Enchantment}. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addEnchantment(Enchantment enchantment, int level) { + + this.itemStack.addEnchantment(enchantment, level); + return this; + + } + + /** + * Add multiple {@link Enchantment} to the ItemStack. + * @param enchantments Map of enchantments to be added. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addEnchantments(Map enchantments) { + + this.itemStack.addEnchantments(enchantments); + return this; + + } + + /** + * Add an unsafe {@link Enchantment} to the ItemStack. + * @param enchantment The unsafe {@link Enchantment} to add. + * @param level The level of the {@link Enchantment}. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addUnsafeEnchantment(Enchantment enchantment, int level) { + + this.itemStack.addUnsafeEnchantment(enchantment, level); + return this; + + } + + /** + * Add multiple unsafe {@link Enchantment} to the ItemStack. + * @param enchantments Map of unsafe enchantments to be added. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addUnsafeEnchantments(Map enchantments) { + + this.itemStack.addUnsafeEnchantments(enchantments); + return this; + + } + + /** + * Remove an {@link Enchantment} from the ItemStack. + * @param enchantment The {@link Enchantment} to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeEnchantment(Enchantment enchantment) { + + this.itemStack.removeEnchantment(enchantment); + return this; + + } + + /** + * Set the display name of the ItemStack. + * @param displayName The display name to set. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setDisplayName(String displayName) { + + this.itemMeta.setDisplayName(color(displayName)); + return this; + + } + + /** + * Add a new lore line to the ItemStack. + * @param line The line to add. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addLoreLine(String line) { + + this.lore.add(line); + return this; + + } + + /** + * Add multiple lore lines to the ItemStack. + * @param lines The lines to add. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addLoreLines(String... lines) { + + this.lore.addAll(Arrays.asList(lines)); + return this; + + } + + /** + * Set the lore of the ItemStack. + * @param lore The lore as {@link List} to set. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setLore(List lore) { + + this.lore = lore; + return this; + + } + + /** + * Set the lore of the ItemStack. + * @param lore The lore as {@link String[]} to set. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setLore(String[] lore) { + + this.lore = Arrays.asList(lore); + return this; + + } + + /** + * Remove a lore line by index. + * @param index The index of the line to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeLore(int index) { + + this.lore.remove(index); + return this; + + } + + /** + * Clear the lore of the ItemStack. + * @return The existing ItemFactory instance. + */ + + public ItemFactory clearLore() { + + this.lore.clear(); + return this; + + } + + /** + * Set the ItemStack unbreakable or not. + * @param unbreakable Whether it should be unbreakable. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setUnbreakable(boolean unbreakable) { + + this.itemMeta.setUnbreakable(unbreakable); + return this; + + } + + /** + * Set the damage of the ItemStack. + * @param damage The damage to set. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setDamage(short damage) { + + ((Damageable) this.itemMeta).setDamage(damage); + return this; + + } + + /** + * Add one {@link ItemFlag} to the ItemStack. + * @param flag The flag to add. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addItemFlag(ItemFlag flag) { + + this.itemMeta.addItemFlags(flag); + return this; + + } + + /** + * Add multiple {@link ItemFlag} to the ItemStack. + * @param flags The flags to add. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addItemFlag(ItemFlag... flags) { + + this.itemMeta.addItemFlags(flags); + return this; + + } + + /** + * Remove an {@link ItemFlag} from the ItemStack. + * @param flag The flag to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeItemFlag(ItemFlag flag) { + + this.itemMeta.removeItemFlags(flag); + return this; + + } + + /** + * Remove multiple {@link ItemFlag} from the ItemStack. + * @param flags The flags to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeItemFlag(ItemFlag... flags) { + + this.itemMeta.removeItemFlags(flags); + return this; + + } + + /** + * Add an {@link AttributeModifier} to the ItemStack. + * @param attribute The {@link Attribute} for the modifier. + * @param modifier The {@link AttributeModifier} to add. + * @return The existing ItemFactory instance. + */ + + public ItemFactory addAttributeModifier(Attribute attribute, AttributeModifier modifier) { + + this.itemMeta.addAttributeModifier(attribute, modifier); + return this; + + } + + /** + * Remove an {@link AttributeModifier} by {@link Attribute} + * @param attribute The {@link Attribute} of the modifier to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeAttributeModifier(Attribute attribute) { + + this.itemMeta.removeAttributeModifier(attribute); + return this; + + } + + /** + * Remove an {@link AttributeModifier} by {@link EquipmentSlot} + * @param attribute The {@link EquipmentSlot} of the modifier to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeAttributeModifier(EquipmentSlot attribute) { + + this.itemMeta.removeAttributeModifier(attribute); + return this; + + } + + /** + * Remove an {@link AttributeModifier} by {@link Attribute} and modifier. + * @param attribute The {@link Attribute} of the modifier to remove. + * @param modifier The {@link AttributeModifier} to remove. + * @return The existing ItemFactory instance. + */ + + public ItemFactory removeAttributeModifier(Attribute attribute, AttributeModifier modifier) { + + this.itemMeta.removeAttributeModifier(attribute, modifier); + return this; + + } + + /** + * Change if the ItemStack should glow or not. + * @param glowing Whether the ItemStack shoud glow. + * @return The existing ItemFactory instance. + */ + + public ItemFactory setGlowing(boolean glowing) { + + Enchantment enchantment = this.itemStack.getType() != Material.BOW ? Enchantment.ARROW_INFINITE : Enchantment.LUCK; + + if(glowing) { + this.removeEnchantment(enchantment); + this.removeItemFlag(ItemFlag.HIDE_ENCHANTS); + } else { + this.addEnchantment(enchantment, 10); + this.addItemFlag(ItemFlag.HIDE_ENCHANTS); + } + + return this; + + } + + /** + * Hide all attributes of the ItemStack. + * @return The existing ItemFactory instance. + */ + + public ItemFactory hideAttributes() { + + this.addItemFlag(ItemFlag.HIDE_ATTRIBUTES); + return this; + + } + + /** + * Show all attributes of the ItemStack. + * @return The existing ItemFactory instance. + */ + + public ItemFactory showAttributes() { + + this.removeItemFlag(ItemFlag.HIDE_ATTRIBUTES); + return this; + + } + + /** + * Build the {@link ItemStack}. + * @return The newly created {@link ItemStack}. + * @since 1.0.0 + */ + + public ItemStack build() { + + List newLore = new ArrayList<>(); + this.lore.forEach((lore) -> newLore.add(color(lore))); + + this.itemMeta.setLore(newLore); + this.itemStack.setItemMeta(this.itemMeta); + + return itemStack; + + } + + /** + * Color format a String (replace '&'). + * @param color The String to format. + * @return The color formatted String. + */ + + private String color(String color) { + + return ChatColor.translateAlternateColorCodes('&', color); + + } + +} diff --git a/src/main/java/me/magnum/breedablepets/util/ItemUtil.java b/src/main/java/me/magnum/breedablepets/util/ItemUtil.java index 2e78c0d..f95a45e 100644 --- a/src/main/java/me/magnum/breedablepets/util/ItemUtil.java +++ b/src/main/java/me/magnum/breedablepets/util/ItemUtil.java @@ -25,7 +25,6 @@ */ package me.magnum.breedablepets.util; -import me.magnum.lib.ItemBuilder; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -44,24 +43,22 @@ private ItemStack makeEgg () { private ItemStack makeEgg (boolean fertile) { ItemStack egg; if (fertile) { - egg = new ItemBuilder(Material.EGG) - .setName("§eFertile Parrot Egg") + egg = new ItemFactory(Material.EGG) + .setDisplayName("§eFertile Parrot Egg") .addLoreLine("Did it just move?") - .addLoreLine("I think it is ready to hatch!") - .toItemStack(); + .addLoreLine("I think it is ready to hatch!").build(); } else { - egg = new ItemBuilder(Material.EGG) - .setName("§aParrot Egg") + egg = new ItemFactory(Material.EGG) + .setDisplayName("§aParrot Egg") .addLoreLine("We don't know how it got here,") .addLoreLine("but it might hatch a parrot!") - .toItemStack(); + .build(); } return egg; } public ItemStack birdFood () { - ItemStack bf = new ItemBuilder(Material.PUMPKIN_SEEDS).toItemStack(); - return bf; + return new ItemFactory(Material.PUMPKIN_SEEDS).build(); } } diff --git a/src/main/java/me/magnum/breedablepets/util/Messages.java b/src/main/java/me/magnum/breedablepets/util/Messages.java new file mode 100644 index 0000000..bff6c83 --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/Messages.java @@ -0,0 +1,16 @@ +package me.magnum.breedablepets.util; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.entity.Player; + +public class Messages { + public static void sendBar(Player pl, String title) { + try { + pl.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(Common.colorize(title))); + + } catch (final Throwable t) { + Common.tell(pl, title); + } + } +} diff --git a/src/main/java/me/magnum/breedablepets/util/SimpleConfig.java b/src/main/java/me/magnum/breedablepets/util/SimpleConfig.java new file mode 100644 index 0000000..4241c6f --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/SimpleConfig.java @@ -0,0 +1,154 @@ +/* + * Base with comment and header features created by Log-out + * https://bukkit.org/threads/tut-custom-yaml-configurations-with-comments.142592/ + * Updated by Magnum1997 to auto update config files from resources + */ + +package me.magnum.breedablepets.util; + +import de.leonhard.storage.internal.FileData; +import de.leonhard.storage.internal.FlatFile; +import me.magnum.Breedable; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class SimpleConfig { +private JavaPlugin plugin; + private int comments; + private SimpleConfigManager manager; + + private File file; + private FileConfiguration config; + + public SimpleConfig (InputStreamReader configStream, File configFile, int comments, JavaPlugin plugin) { + this.plugin = plugin; + this.comments = comments; + this.manager = new SimpleConfigManager(plugin); + + this.file = configFile; + this.config = YamlConfiguration.loadConfiguration(configStream); + } + + public Object get (String path) { + return this.config.get(path); + } + + public Object get (String path, Object def) { + return this.config.get(path, def); + } + + public String getString (String path) { + return this.config.getString(path); + } + + public String getString (String path, String def) { + return this.config.getString(path, def); + } + + public int getInt (String path) { + return this.config.getInt(path); + } + + public int getInt (String path, int def) { + return this.config.getInt(path, def); + } + + public boolean getBoolean (String path) { + return this.config.getBoolean(path); + } + + public boolean getBoolean (String path, boolean def) { + return this.config.getBoolean(path, def); + } + + public void createSection (String path) { + this.config.createSection(path); + } + + public ConfigurationSection getConfigurationSection (String path) { + return this.config.getConfigurationSection(path); + } + + public double getDouble (String path) { + return this.config.getDouble(path); + } + + public double getDouble (String path, double def) { + return this.config.getDouble(path, def); + } + + public List getList (String path) { + return this.config.getList(path); + } + + public List getList (String path, List def) { + return this.config.getList(path, def); + } + + public boolean contains (String path) { + return this.config.contains(path); + } + + public void removeKey (String path) { + this.config.set(path, null); + } + + public void set (String path, Object value) { + this.config.set(path, value); + } + + public void set (String path, Object value, String comment) { + if (! this.config.contains(path)) { + this.config.set(manager.getPluginName() + "_COMMENT_" + comments, " " + comment); + comments++; + } + + this.config.set(path, value); + + } + + public void set (String path, Object value, String[] comment) { + + for (String comm : comment) { + + if (! this.config.contains(path)) { + this.config.set(manager.getPluginName() + "_COMMENT_" + comments, " " + comm); + comments++; + } + + } + + this.config.set(path, value); + + } + + public void setHeader (String[] header) { + manager.setHeader(this.file, header); + this.comments = header.length + 2; + this.reloadConfig(); + } + + public void reloadConfig () { + this.config = YamlConfiguration.loadConfiguration(manager.getConfigContent(file)); + } + + public void saveConfig () { + String config = this.config.saveToString(); + manager.saveConfig(config, this.file); + + } + + public Set getKeys () { + return this.config.getKeys(false); + } + +} diff --git a/src/main/java/me/magnum/breedablepets/util/SimpleConfigManager.java b/src/main/java/me/magnum/breedablepets/util/SimpleConfigManager.java new file mode 100644 index 0000000..299a13a --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/SimpleConfigManager.java @@ -0,0 +1,424 @@ +package me.magnum.breedablepets.util; + +/* + * Base with comment and header features created by Log-out + * https://bukkit.org/threads/tut-custom-yaml-configurations-with-comments.142592/ + * Updated by Magnum1997 to auto update config files from resources + */ + +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +public class SimpleConfigManager { + + private JavaPlugin plugin; + + /** + * Manage custom configurations and files + */ + public SimpleConfigManager (JavaPlugin plugin) { + this.plugin = plugin; + } + + /** + * Get new configuration with header + * + * @param filePath - Path to file + * @return - New SimpleConfig + */ + public SimpleConfig getNewConfig (String filePath, String[] header) { + + File file = this.getConfigFile(filePath); + + if (! file.exists()) { + this.prepareFile(filePath); + + if (header != null && header.length != 0) { + this.setHeader(file, header); + } + + } + + SimpleConfig config = new SimpleConfig(this.getConfigContent(filePath), file, this.getCommentsNum(file), plugin); + return config; + + } + + /** + * Get new configuration. + *

It will be blank unless (@link useDefaults) is true + * and include it in resources.

+ * + * @param filePath - Path to file + * @return - New SimpleConfig + */ + public SimpleConfig getNewConfig (String filePath) { + return this.getNewConfig(filePath, null); + } + + /** + * Get configuration file from string + * + * @param file - File path + * @return - New file object + */ + private File getConfigFile (String file) { + + if (file == null || file.isEmpty()) { + return null; + } + + File configFile; + + if (file.contains("/")) { + + if (file.startsWith("/")) { + configFile = new File(plugin.getDataFolder() + file.replace("/", File.separator)); + } + else { + configFile = new File(plugin.getDataFolder() + File.separator + file.replace("/", File.separator)); + } + + } + else { + configFile = new File(plugin.getDataFolder(), file); + } + + return configFile; + + } + + /** + * Create new file for config and copy resource into it + * + * @param filePath - Path to file + * @param resource - Resource to copy + */ + public void prepareFile (String filePath, String resource) { + + File file = this.getConfigFile(filePath); + + if (file.exists()) { + return; + } + + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + + if (resource != null && ! resource.isEmpty()) { + this.copyResource(plugin.getResource(resource), file); + } + + } + catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * Create new file for config without resource + * + * @param filePath - File to create + */ + public void prepareFile (String filePath) { + this.prepareFile(filePath, null); + } + + /** + * Adds header block to config + * + * @param file - Config file + * @param header - Header lines + */ + public void setHeader (File file, String[] header) { + + if (! file.exists()) { + return; + } + + try { + String currentLine; + StringBuilder config = new StringBuilder(); + BufferedReader reader = new BufferedReader(new FileReader(file)); + + while ((currentLine = reader.readLine()) != null) { + config.append(currentLine + "\n"); + } + + reader.close(); + config.append("# +----------------------------------------------------+ #\n"); + + for (String line : header) { + + if (line.length() > 50) { + continue; + } + + int lenght = (50 - line.length()) / 2; + StringBuilder finalLine = new StringBuilder(line); + + for (int i = 0; i < lenght; i++) { + finalLine.append(" "); + finalLine.reverse(); + finalLine.append(" "); + finalLine.reverse(); + } + + if (line.length() % 2 != 0) { + finalLine.append(" "); + } + + config.append("# < " + finalLine.toString() + " > #\n"); + + } + + config.append("# +----------------------------------------------------+ #"); + + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write(this.prepareConfigString(config.toString())); + writer.flush(); + writer.close(); + + } + catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * Read file and make comments SnakeYAML friendly + * + * @param file - Path to file + * @return - File as Input Stream + */ + public InputStreamReader getConfigContent (File file) { + + if (! file.exists()) { + return null; + } + + try { + int commentNum = 0; + + String addLine; + String currentLine; + String pluginName = this.getPluginName(); + + StringBuilder whole = new StringBuilder(); + BufferedReader reader = new BufferedReader(new FileReader(file)); + + while ((currentLine = reader.readLine()) != null) { + + if (currentLine.startsWith("#")) { + addLine = currentLine.replaceFirst("#", pluginName + "_COMMENT_" + commentNum + ":"); + whole.append(addLine + "\n"); + commentNum++; + + } + else { + whole.append(currentLine + "\n"); + } + + } + + String config = whole.toString(); + InputStream configStream = new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8)); + InputStreamReader configStreamReader = new InputStreamReader(configStream); + + reader.close(); + return configStreamReader; + + } + catch (IOException e) { + e.printStackTrace(); + return null; + } + + } + + + /** + * Get comments from file + * + * @param file - File + * @return - Comments number + */ + private int getCommentsNum (File file) { + + if (! file.exists()) { + return 0; + } + + try { + int comments = 0; + String currentLine; + + BufferedReader reader = new BufferedReader(new FileReader(file)); + + while ((currentLine = reader.readLine()) != null) { + + if (currentLine.startsWith("#")) { + comments++; + } + + } + + reader.close(); + return comments; + + } + catch (IOException e) { + e.printStackTrace(); + return 0; + } + + } + + /** + * Get config content from file + * + * @param filePath - Path to file + * @return - readied file + */ + public InputStreamReader getConfigContent (String filePath) { + return this.getConfigContent(this.getConfigFile(filePath)); + } + + + private String prepareConfigString (String configString) { + + int lastLine = 0; + int headerLine = 0; + + String[] lines = configString.split("\n"); + StringBuilder config = new StringBuilder(); + + for (String line : lines) { + + if (line.startsWith(this.getPluginName() + "_COMMENT")) { + String comment = "#" + line.trim().substring(line.indexOf(":") + 1); + + if (comment.startsWith("# +-")) { + + /* + * If header line = 0 then it is + * header start, if it's equal + * to 1 it's the end of header + */ + + if (headerLine == 0) { + config.append(comment + "\n"); + + lastLine = 0; + headerLine = 1; + + } + else if (headerLine == 1) { + config.append(comment + "\n\n"); + + lastLine = 0; + headerLine = 0; + + } + + } + else { + + /* + * Last line = 0 - Comment + * Last line = 1 - Normal path + */ + + String normalComment; + + if (comment.startsWith("# ' ")) { + normalComment = comment.substring(0, comment.length() - 1).replaceFirst("# ' ", "# "); + } + else { + normalComment = comment; + } + + if (lastLine == 0) { + config.append(normalComment + "\n"); + } + else if (lastLine == 1) { + config.append("\n" + normalComment + "\n"); + } + + lastLine = 0; + + } + + } + else { + config.append(line + "\n"); + lastLine = 1; + } + + } + + return config.toString(); + + } + + + /** + * Saves configuration to file + * + * @param configString - Config string + * @param file - Config file + */ + public void saveConfig (String configString, File file) { + String configuration = this.prepareConfigString(configString); + + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write(configuration); + writer.flush(); + writer.close(); + + } + catch (IOException e) { + e.printStackTrace(); + } + + } + + public String getPluginName () { + return plugin.getDescription().getName(); + } + + /** + * Copy resource from Input Stream to file + * + * @param resource - Resource from .jar + * @param file - File to write + */ + private void copyResource (InputStream resource, File file) { + + try { + OutputStream out = new FileOutputStream(file); + + int lenght; + byte[] buf = new byte[1024]; + + while ((lenght = resource.read(buf)) > 0) { + out.write(buf, 0, lenght); + } + + out.close(); + resource.close(); + + } + catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/me/magnum/breedablepets/util/SpawnPets.java b/src/main/java/me/magnum/breedablepets/util/SpawnPets.java index 5233075..c9e4f15 100644 --- a/src/main/java/me/magnum/breedablepets/util/SpawnPets.java +++ b/src/main/java/me/magnum/breedablepets/util/SpawnPets.java @@ -26,8 +26,7 @@ package me.magnum.breedablepets.util; -import me.magnum.breedablepets.Main; -import me.magnum.lib.SimpleConfig; +import me.magnum.Breedable; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -35,27 +34,29 @@ import org.bukkit.entity.Parrot; import org.bukkit.entity.Player; +import java.util.Objects; + public class SpawnPets { - private static SimpleConfig cfg = Main.cfg; - + public SpawnPets () { } public static void newParrot (Player player, Location location) { World world = player.getWorld(); + location = world.getHighestBlockAt(location).getLocation().add(0,1,0); Parrot parrot = (Parrot) world.spawnEntity(location, EntityType.PARROT); - parrot.setTamed(cfg.getBoolean("hatches.tamed")); - parrot.setHealth(1); //todo add to config + parrot.setTamed(Breedable.getPlugin().getCfg().getBoolean("hatches.tamed")); + parrot.setHealth(1); // TODO add to config parrot.setVariant(Parrot.Variant.RED); if (parrot.isTamed()) { parrot.setOwner(player); parrot.setSitting(true); } - if (Main.cfg.getBoolean("hatches.named")) { + if (Breedable.getPlugin().getCfg().getBoolean("hatches.named")) { parrot.setCustomNameVisible(true); - parrot.setCustomName(ChatColor.translateAlternateColorCodes('&', Main.cfg.getString("hatches.name"))); + parrot.setCustomName(ChatColor.translateAlternateColorCodes('&', Objects.requireNonNull(Breedable.getPlugin().getCfg().getString("hatches.name")))); } } } diff --git a/src/main/java/me/magnum/breedablepets/util/YamlHelper.java b/src/main/java/me/magnum/breedablepets/util/YamlHelper.java new file mode 100644 index 0000000..1f4dc8f --- /dev/null +++ b/src/main/java/me/magnum/breedablepets/util/YamlHelper.java @@ -0,0 +1,96 @@ +package me.magnum.breedablepets.util; + +import de.leonhard.storage.Yaml; +import lombok.NoArgsConstructor; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@NoArgsConstructor +public class YamlHelper { + + private String[] header; + private int commentsCounter; + + public List framedHeader (String... header) { + List stringList = new ArrayList <>(); + String border = "# ┼─────────────────────────────────────────────────────┼ #"; + stringList.add(border); + + for (String line : header) { + StringBuilder builder = new StringBuilder(); + if (line.length() > 50) { + continue; + } + + int length = (50 - line.length()) / 2; + StringBuilder finalLine = new StringBuilder(line); + + for (int i = 0; i < length; i++) { + finalLine.append(" "); + finalLine.reverse(); + finalLine.append(" "); + finalLine.reverse(); + } + + if (line.length() % 2 != 0) { + finalLine.append(" "); + } + + builder.append("# │").append(finalLine.toString()).append(" │#"); + stringList.add(builder.toString()); + } + stringList.add(border); + return stringList; + } + + public void setComment (Yaml yaml, String path, Object value, String comment) { + int comments = getCommentsNum(yaml.getFile()); + if (! yaml.contains(path)) { + yaml.set(yaml.getName() + "_COMMENT_" + comments, " " + comment); + } + yaml.set(path, value); + } + + /** + * Get comments from file + * + * @param file - File + * @return - Comments number + */ + private int getCommentsNum (File file) { + + if (! file.exists()) { + return 0; + } + + try { + int comments = 0; + String currentLine; + + BufferedReader reader = new BufferedReader(new FileReader(file)); + + while ((currentLine = reader.readLine()) != null) { + + if (currentLine.startsWith("#")) { + comments++; + } + + } + + reader.close(); + return comments; + + } + catch (IOException e) { + e.printStackTrace(); + return 0; + } + + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1542db8..e1838f0 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,4 @@ -# Config for @NAME@ version @VERSION@ -version: @VERSION@ -# base chance that feeding a _tamed_ parrot will produce an egg. +# Base chance that feeding a _tamed_ parrot will produce an egg. egg-chance: 10 # chance that feeding with a mate nearby produces an egg paired-egg-chance: 20 @@ -13,7 +11,7 @@ rare-chance: 1 # chance modifiers increase chance of eggs depending on what food you use # modifier of 0 does not change base chance -# This is for future version todo Add food modifiers +# This is for future version # TODO Add food modifiers modifier: wheat: 10 beetroot: 20 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml deleted file mode 100644 index c6b6747..0000000 --- a/src/main/resources/plugin.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: @NAME@ -main: @MAIN@ -version: @VERSION@ -api-version: 1.13 -author: Magnum1997