diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index 1d2f8f14..92facabd 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -8,6 +8,9 @@ on:
branches:
- main
+permissions:
+ contents: read
+
jobs:
build:
if: startsWith(github.event.head_commit.message, '[CI skip]') == false
@@ -16,19 +19,24 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- - name: Set up JDK 17
+ - name: Set up JDK 21
uses: actions/setup-java@v4
with:
- java-version: 17
+ java-version: 21
distribution: temurin
- - name: Validate Gradle wrapper
- uses: gradle/wrapper-validation-action@v2
+ - name: Cache Gradle packages
+ uses: actions/cache@v4
+ with:
+ path: ~/.gradle/caches
+ key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}"
+ restore-keys: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}"
+
+ - name: Setup gradle
+ uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
- uses: gradle/gradle-build-action@v3
- with:
- arguments: build
+ run: ./gradlew clean shadowJar
- name: Get build artifact ready
run: mkdir staging && cp build/libs/*.jar staging
@@ -36,5 +44,5 @@ jobs:
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
- name: dev-build
+ name: preview-build
path: staging
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index 763a754b..174a97dc 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -7,31 +7,43 @@ on:
types: [opened, synchronize, reopened]
branches:
- main
+
+permissions:
+ contents: read
+
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - name: Checkout repository
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Set up JDK 17
+
+ - name: Set up JDK 21
uses: actions/setup-java@v4
with:
- java-version: 17
- distribution: 'temurin'
+ java-version: 21
+ distribution: temurin
+
- name: Cache SonarCloud packages
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
+
- name: Cache Gradle packages
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.gradle/caches
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- restore-keys: ${{ runner.os }}-gradle
+ key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}"
+ restore-keys: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}"
+
+ - name: Setup gradle
+ uses: gradle/actions/setup-gradle@v4
+
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 3c2a5873..00000000
--- a/build.gradle
+++ /dev/null
@@ -1,69 +0,0 @@
-plugins {
- id 'java'
- id 'com.github.johnrengelman.shadow' version '8.1.1'
- id 'org.sonarqube' version '4.4.1.3373'
- id 'io.freefair.lombok' version '8.6'
- id 'net.minecrell.plugin-yml.bukkit' version '0.6.0'
-}
-
-group = 'io.github.slimefunguguproject'
-version = 'UNOFFICIAL'
-description = 'Bump'
-
-java {
- sourceCompatibility = JavaVersion.VERSION_16
-}
-
-tasks.withType(JavaCompile) {
- options.encoding = 'UTF-8'
-}
-
-repositories {
- mavenLocal()
- mavenCentral()
-
- maven {
- url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/')
- }
-
- maven {
- url = uri('https://jitpack.io')
- }
-
- maven {
- url = uri('https://s01.oss.sonatype.org/content/repositories/snapshots/')
- }
-}
-
-dependencies {
- implementation 'net.guizhanss:GuizhanLib-api:1.7.6'
- implementation 'dev.sefiraat:SefiLib:0.2.6'
- implementation 'org.bstats:bstats-bukkit:3.0.2'
-
- compileOnly 'org.spigotmc:spigot-api:1.20.4-R0.1-SNAPSHOT'
- compileOnly 'io.github.Slimefun:Slimefun4:RC-37'
- compileOnly 'com.google.code.findbugs:jsr305:3.0.2'
-}
-
-shadowJar {
- relocate 'net.guizhanss.guizhanlib', 'io.github.slimefunguguproject.bump.libs.guizhanlib'
- relocate 'dev.sefiraat.sefilib', 'io.github.slimefunguguproject.bump.libs.sefilib'
- relocate 'org.bstats', 'io.github.slimefunguguproject.bump.libs.bstats'
- minimize()
-}
-
-bukkit {
- main = 'io.github.slimefunguguproject.bump.implementation.Bump'
- apiVersion = '1.16'
- authors = ['bxx2004', 'LobbyTech-MC', 'zimzaza4', 'haiman233', 'ybw0014']
- depend = ['Slimefun']
- softDepend = ['GuizhanLibPlugin']
-}
-
-sonar {
- properties {
- property "sonar.projectKey", "SlimefunGuguProject_Bump"
- property "sonar.organization", "slimefunguguproject"
- property "sonar.host.url", "https://sonarcloud.io"
- }
-}
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 00000000..d100277e
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,76 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
+plugins {
+ kotlin("jvm") version "2.0.20"
+ id("com.gradleup.shadow") version "8.3.0"
+ id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
+ id("org.sonarqube") version "5.0.0.4638"
+}
+
+group = "io.github.slimefunguguproject"
+version = "UNOFFICIAL"
+description = "Bump"
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ maven("https://repo.papermc.io/repository/maven-public/")
+ maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
+ maven("https://jitpack.io")
+ maven("https://repo.alessiodp.com/releases/")
+}
+
+dependencies {
+ compileOnly(kotlin("stdlib"))
+ compileOnly(kotlin("reflect"))
+ compileOnly("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
+ compileOnly("com.github.Slimefun:Slimefun4:e02a0f61d1")
+ implementation("net.guizhanss:GuizhanLib-api:1.8.1")
+ implementation("dev.sefiraat:SefiLib:0.2.6") {
+ exclude("io.github.baked-libs", "dough-api")
+ }
+ implementation("org.bstats:bstats-bukkit:3.0.3")
+ implementation("net.byteflux:libby-bukkit:1.3.1")
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_21
+ targetCompatibility = JavaVersion.VERSION_21
+}
+
+tasks.compileKotlin {
+ compilerOptions {
+ javaParameters = true
+ jvmTarget = JvmTarget.JVM_21
+ }
+}
+
+tasks.shadowJar {
+ fun doRelocate(from: String, to: String? = null) {
+ val last = from.split(".").last()
+ relocate(from, "io.github.slimefunguguproject.bump.libs.${to ?: last}")
+ }
+ doRelocate("net.guizhanss.guizhanlib")
+ doRelocate("dev.sefiraat.sefilib")
+ doRelocate("org.bstats")
+ doRelocate("net.byteflux.libby")
+ doRelocate("io.papermc.lib", "paperlib")
+ minimize()
+ archiveClassifier = ""
+}
+
+bukkit {
+ main = "io.github.slimefunguguproject.bump.Bump"
+ apiVersion = "1.18"
+ authors = listOf("bxx2004", "LobbyTech-MC", "zimzaza4", "haiman233", "ybw0014")
+ depend = listOf("Slimefun")
+ softDepend = listOf("GuizhanLibPlugin", "SlimefunTranslation")
+}
+
+sonar {
+ properties {
+ property("sonar.projectKey", "SlimefunGuguProject_Bump")
+ property("sonar.organization", "slimefunguguproject")
+ property("sonar.host.url", "https://sonarcloud.io")
+ }
+}
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index 8c850755..00000000
--- a/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-version = 2.0-UNOFFICIAL
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 1af9e093..9355b415 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index 04890ca0..00000000
--- a/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = 'Bump'
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 00000000..e2497239
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1,2 @@
+rootProject.name = "Bump"
+System.setProperty("sonar.gradle.skipCompile", "true")
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.java b/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.java
deleted file mode 100644
index 2f650fba..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package io.github.slimefunguguproject.bump.api.appraise;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.attribute.Attribute;
-
-import lombok.Getter;
-import lombok.NonNull;
-
-/**
- * This class represents a single {@link Attribute} with range and weight.
- *
- * @author ybw0014
- */
-@Getter
-public final class AppraiseAttribute {
- @NonNull
- private final Attribute attribute;
- private final double min;
- private final double max;
-
- private double weight = -1;
-
- @ParametersAreNonnullByDefault
- AppraiseAttribute(Attribute attribute, double min, double max) {
- Preconditions.checkArgument(attribute != null, "Attribute cannot be null");
- Preconditions.checkArgument(min <= max, "The minimum value cannot be larger than the maximum value");
-
- this.attribute = attribute;
- this.min = min;
- this.max = max;
- }
-
- @ParametersAreNonnullByDefault
- AppraiseAttribute(Attribute attribute, double min, double max, double weight) {
- this(attribute, min, max);
-
- this.weight = weight;
- }
-
- /**
- * Set the weight of this attribute.
- *
- * Can only change when weight is not designated yet.
- *
- * @param weight The weight of this attribute.
- */
- public void setWeight(double weight) {
- if (this.weight != -1) {
- throw new UnsupportedOperationException("You cannot change the weight when it is set");
- }
- this.weight = weight;
- }
-
- @Override
- @Nonnull
- public String toString() {
- return "AppraiseAttribute[" + attribute
- + ", " + min + " - " + max + ", " + weight + "]";
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof AppraiseAttribute anotherAttribute) {
- return getAttribute() == anotherAttribute.getAttribute()
- && getMin() == anotherAttribute.getMin()
- && getMax() == anotherAttribute.getMax()
- && getWeight() == anotherAttribute.getWeight();
- } else {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- int hash = 5;
- hash = 47 * hash + this.attribute.hashCode();
- hash = 13 * hash + Double.hashCode(this.min);
- hash = 13 * hash + Double.hashCode(this.max);
- hash = 13 * hash + Double.hashCode(this.weight);
- return hash;
- }
-
- /**
- * Get the percentage of result value within range.
- *
- * Return range from 0 to 100.
- *
- * @param value The result value.
- *
- * @return The percentage of the result value.
- */
- public double getPercentage(double value) {
- if (value <= min) {
- return 0;
- } else if (value >= max) {
- return 100;
- } else {
- return (value - min) / (max - min) * 100.0D;
- }
- }
-
- /**
- * Get the weighted percentage of result value.
- *
- * @param value The result value.
- *
- * @return The weighted percentage of the result value.
- */
- public double getWeightedPercentage(double value) {
- return getPercentage(value) * weight / 100.D;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.java b/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.java
deleted file mode 100644
index 57f99ca3..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package io.github.slimefunguguproject.bump.api.appraise;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Material;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.attribute.AttributeModifier;
-import org.bukkit.inventory.EquipmentSlot;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.Utils;
-import io.github.slimefunguguproject.bump.utils.ValidateUtils;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.slimefunguguproject.bump.utils.tags.BumpTag;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil;
-
-import lombok.Getter;
-
-/**
- * An {@link AppraiseResult} contains results of attributes and the weights.
- *
- * @author ybw0014
- */
-@Getter
-@SuppressWarnings("ConstantConditions")
-public final class AppraiseResult {
- /**
- * This is a reference to the {@link AppraiseType} that generates this {@link AppraiseResult}.
- */
- private final AppraiseType appraiseType;
-
- /**
- * This unmodifiable map stores the {@link AppraiseAttribute} and result.
- */
- private final Map result;
-
- /**
- * This represents the calculated overall percentage.
- */
- private final double totalPercentage;
-
- /**
- * Construct this {@link AppraiseResult} from {@link Builder}
- *
- * @param builder The {@link Builder} to construct this {@link AppraiseResult} from.
- */
- private AppraiseResult(@Nonnull Builder builder) {
- this.appraiseType = builder.appraiseType;
- this.result = Map.copyOf(builder.result);
- this.totalPercentage = builder.totalPercentage;
- }
-
- /**
- * This method returns the stars of appraisal result
- * calculated by overall percentage.
- *
- * @return The number of stars of the result
- */
- public byte getStars() {
- for (Map.Entry entry : Bump.getRegistry().getStarThresholds().entrySet()) {
- if (totalPercentage >= entry.getKey()) {
- return entry.getValue();
- }
- }
- return 0;
- }
-
- /**
- * This method applies the appraisal result to given {@link ItemStack}.
- *
- * @param itemStack The {@link ItemStack}.
- */
- @ParametersAreNonnullByDefault
- public void apply(@Nullable ItemStack itemStack) {
- if (!ValidateUtils.noAirItem(itemStack)) {
- throw new IllegalArgumentException("ItemStack cannot be null or air.");
- }
- ItemMeta meta = itemStack.getItemMeta();
- Material material = itemStack.getType();
- byte stars = getStars();
-
- // attributes
- for (Map.Entry entry : result.entrySet()) {
- Attribute attr = entry.getKey().getAttribute();
-
- for (EquipmentSlot slot : appraiseType.getValidEquipmentSlots()) {
- // Check if the material is applicable for slot
- BumpTag tag = BumpTag.getTag(slot.name() + "_SLOT");
- if (tag.isTagged(material)) {
- meta.addAttributeModifier(attr,
- new AttributeModifier(UUID.randomUUID(), appraiseType.getKey().toString(), entry.getValue(), AppraiseUtils.getOperation(attr), slot)
- );
- }
- }
- }
-
- // lore
- String loreLine = Bump.getLocalization().getString("lores.appraised", Utils.getStars(stars));
- if (meta.hasLore()) {
- List lore = meta.getLore();
- for (int i = 0; i < lore.size(); i++) {
- if (lore.get(i).equals(ChatUtil.color(Bump.getLocalization().getString("lores.not-appraised")))) {
- lore.set(i, ChatUtil.color(loreLine));
- break;
- }
- }
- meta.setLore(lore);
- } else {
- List lore = new ArrayList<>();
- lore.add(ChatUtil.color(loreLine));
- meta.setLore(lore);
- }
-
- // pdc
- PersistentDataAPI.setByte(meta, Keys.APPRAISE_LEVEL, stars);
- PersistentDataAPI.setByte(meta, Keys.APPRAISE_VERSION, (byte) 2);
-
- itemStack.setItemMeta(meta);
- }
-
- /**
- * This builder class is used to generate a {@link AppraiseResult}.
- */
- static class Builder {
- private final AppraiseType appraiseType;
- private final Map result = new HashMap<>();
- private double totalPercentage = 0;
-
- Builder(@Nonnull AppraiseType type) {
- appraiseType = type;
- }
-
- /**
- * This method adds an appraised attribute with its value to result.
- *
- * @param attribute The {@link AppraiseAttribute}.
- * @param result The value of the attribute
- *
- * @return This {@link Builder}
- */
- Builder add(AppraiseAttribute attribute, double result) {
- this.result.put(attribute, result);
- totalPercentage += attribute.getWeightedPercentage(result);
- return this;
- }
-
- AppraiseResult build() {
- return new AppraiseResult(this);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.java b/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.java
deleted file mode 100644
index ac15c2cb..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.java
+++ /dev/null
@@ -1,549 +0,0 @@
-package io.github.slimefunguguproject.bump.api.appraise;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.EquipmentSlot;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.api.exceptions.AppraiseTypeKeyConflictException;
-import io.github.slimefunguguproject.bump.core.BumpRegistry;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate;
-
-import net.guizhanss.guizhanlib.utils.RandomUtil;
-import net.guizhanss.guizhanlib.utils.StringUtil;
-
-import lombok.Getter;
-import lombok.experimental.Accessors;
-
-/**
- * This class represents a type of appraise.
- *
- * It holds all {@link AppraiseAttribute appraisal attributes} used in appraising,
- * with applicable equipment settings.
- *
- * @author ybw0014
- */
-@Accessors(makeFinal = true)
-@SuppressWarnings("ConstantConditions")
-public class AppraiseType {
- /**
- * This is the {@link NamespacedKey} of {@link AppraiseType}.
- */
- @Getter
- private final NamespacedKey key;
-
- /**
- * The display name of {@link AppraiseType}.
- */
- @Getter
- private String name;
-
- /**
- * The description of {@link AppraiseType}.
- */
- @Getter
- private List description = new ArrayList<>();
-
- /**
- * The permission required to use this {@link AppraiseType}.
- */
- @Getter
- private String permission;
-
- /**
- * This holds all added {@link AppraiseAttribute}.
- */
- @Getter
- private Set attributes = new LinkedHashSet<>();
-
- /**
- * This indicates the used percentage of added {@link AppraiseAttribute}.
- */
- private double usedPercentage;
-
- /**
- * This indicates whether check equipment material when appraising.
- */
- @Accessors(fluent = true)
- @Getter
- private boolean checkMaterial;
-
- /**
- * This indicates the acceptable type of equipment for appraising.
- */
- @Getter
- private EquipmentType equipmentType = EquipmentType.ANY;
-
- /**
- * This holds all valid {@link Material materials}.
- *
- * When {@link #checkMaterial()} is enabled, the appraisal machine will check
- * the material of specified item.
- */
- @Getter
- private Set validMaterials = EnumSet.noneOf(Material.class);
-
- /**
- * This holds all valid acceptable {@link EquipmentSlot}.
- */
- @Getter
- private Set validEquipmentSlots = EnumSet.noneOf(EquipmentSlot.class);
-
- /**
- * This holds all valid Slimefun item IDs.
- */
- @Getter
- private Set validSlimefunItemIds = new HashSet<>();
-
- /**
- * This indicates the {@link SlimefunAddon} that registered this {@link AppraiseType}.
- *
- * Will be null if this {@link AppraiseType} has not been registered.
- */
- @Getter
- private SlimefunAddon addon;
-
- /**
- * Initialize {@link AppraiseType} with {@link NamespacedKey}.
- *
- * @param key The {@link NamespacedKey} of {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public AppraiseType(NamespacedKey key) {
- Preconditions.checkArgument(key != null, "NamespacedKey cannot be null");
-
- this.key = key;
- this.name = StringUtil.humanize(key.getKey());
- }
-
- /**
- * Retrieve a {@link AppraiseType} by its {@link NamespacedKey}.
- *
- * @param key The {@link NamespacedKey} of the {@link AppraiseType}.
- *
- * @return The {@link AppraiseType} associated with that {@link NamespacedKey}. {@code null} if not exist.
- */
- @Nullable
- public static AppraiseType getByKey(@Nonnull NamespacedKey key) {
- Preconditions.checkArgument(key != null, "NamespacedKey cannot be null");
- return Bump.getRegistry().getAppraiseTypeKeys().get(key);
- }
-
- /**
- * Set the name of this {@link AppraiseType}.
- *
- * @param name The name.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType setName(String name) {
- checkState();
- Preconditions.checkArgument(name != null, "Name cannot be null");
- this.name = name;
- return this;
- }
-
- /**
- * Set the description of this {@link AppraiseType}.
- *
- * @param description The description, in array.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType setDescription(String... description) {
- Validate.noNullElements(description);
- return setDescription(Arrays.asList(description));
- }
-
- /**
- * Set the description of this {@link AppraiseType}.
- *
- * @param description The description, in array.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType setDescription(List description) {
- checkState();
- Validate.noNullElements(description);
- this.description = description;
- return this;
- }
-
- /**
- * Set the permission of this {@link AppraiseType}.
- *
- * @param permission The permission.
- *
- * @return This {@link AppraiseType}.
- */
- public final AppraiseType setPermission(@Nullable String permission) {
- checkState();
- this.permission = permission;
- return this;
- }
-
- /**
- * Check if {@link Player} have permission for this {@link AppraiseType}.
- *
- * @param p The {@link Player} to be checked.
- *
- * @return If the {@link Player} have permission.
- */
- @ParametersAreNonnullByDefault
- public boolean hasPermission(Player p) {
- Preconditions.checkArgument(p != null, "Player cannot be null");
-
- if (getPermission() == null) {
- return true;
- } else {
- return p.hasPermission(getPermission());
- }
- }
-
- /**
- * Set if this {@link AppraiseType} check item material when appraising.
- *
- * @param value Whether to check item material.
- *
- * @return This {@link AppraiseType}.
- */
- public final AppraiseType checkMaterial(boolean value) {
- checkState();
- this.checkMaterial = value;
- return this;
- }
-
- /**
- * Set the {@link EquipmentType} of this {@link AppraiseType}.
- *
- * @param type The {@link EquipmentType}.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType setEquipmentType(EquipmentType type) {
- checkState();
- this.equipmentType = type;
- return this;
- }
-
- /**
- * This method adds an {@link Attribute} as {@link AppraiseAttribute}.
- *
- * @param attribute The {@link Attribute} to be added
- * @param min The minimum value of attribute
- * @param max The maximum value of attribute
- * @param weight The weight used to calculate overall star rate
- * (between 0 and 100, -1 means dividing remaining weight)
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addAttribute(Attribute attribute, double min, double max, double weight) {
- checkState();
-
- Preconditions.checkArgument(weight == -1 || (weight >= 0 && weight <= 100), "The weight should be -1 or between 0 and 100");
- if (weight != -1) {
- Preconditions.checkArgument(usedPercentage + weight <= 100, "The overall weight exceeds 100");
- }
-
- AppraiseAttribute attr = new AppraiseAttribute(attribute, min, max, weight);
- attributes.add(attr);
-
- if (weight != -1) {
- usedPercentage += weight;
- }
-
- return this;
- }
-
- /**
- * This method adds an {@link Attribute} as {@link AppraiseAttribute}, without weight.
- *
- * @param attribute The {@link Attribute} to be changed
- * @param min The minimum value of attribute
- * @param max The maximum value of attribute
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addAttribute(Attribute attribute, double min, double max) {
- return addAttribute(attribute, min, max, -1);
- }
-
- /**
- * Add valid materials.
- *
- * @param materials The array of valid {@link Material}.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidMaterials(Material... materials) {
- return addValidMaterials(Arrays.asList(materials));
- }
-
- /**
- * Add valid materials.
- *
- * @param materials The {@link Collection} of valid {@link Material}.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidMaterials(Collection materials) {
- checkState();
- for (Material mat : materials) {
- if (mat == Material.AIR) {
- throw new IllegalArgumentException("Material cannot be AIR");
- }
- }
- validMaterials.addAll(materials);
- return this;
- }
-
- /**
- * Add valid Slimefun item ids.
- *
- * @param slimefunItemIds The array of valid Slimefun item ids.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidSlimefunItemIds(String... slimefunItemIds) {
- Validate.noNullElements(slimefunItemIds);
- return addValidSlimefunItemIds(Arrays.asList(slimefunItemIds));
- }
-
- /**
- * Add valid Slimefun item ids.
- *
- * @param slimefunItemIds The {@link Collection} of valid Slimefun item ids.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidSlimefunItemIds(Collection slimefunItemIds) {
- checkState();
- Validate.noNullElements(slimefunItemIds);
- validSlimefunItemIds.addAll(slimefunItemIds);
- return this;
- }
-
- /**
- * Add valid equipment slots.
- *
- * @param equipmentSlots The array of valid equipment slots.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidEquipmentSlots(EquipmentSlot... equipmentSlots) {
- Validate.noNullElements(equipmentSlots);
- return addValidEquipmentSlots(Arrays.asList(equipmentSlots));
- }
-
- /**
- * Add valid equipment slots.
- *
- * @param equipmentSlots The {@link Collection} of valid equipment slots.
- *
- * @return This {@link AppraiseType}.
- */
- @ParametersAreNonnullByDefault
- public final AppraiseType addValidEquipmentSlots(Collection equipmentSlots) {
- checkState();
- Validate.noNullElements(equipmentSlots);
- validEquipmentSlots.addAll(equipmentSlots);
- return this;
- }
-
- /**
- * This method will register this {@link AppraiseType}.
- * It will calculate the attributes without weight,
- * and divide the remaining overall weight.
- *
- * @param addon The {@link SlimefunAddon} that register this {@link AppraiseType}
- *
- * @return {@link AppraiseType} itself
- */
- public final AppraiseType register(@Nonnull SlimefunAddon addon) {
- Preconditions.checkArgument(addon != null, "Addon cannot be null");
-
- final BumpRegistry registry = Bump.getRegistry();
-
- // check id
- AppraiseType existing = registry.getAppraiseTypeKeys().get(key);
- if (existing != null) {
- throw new AppraiseTypeKeyConflictException(this, existing);
- }
-
- final Set noWeightAttributes = attributes.stream()
- .filter(appraiseAttribute -> appraiseAttribute.getWeight() == -1)
- .collect(Collectors.toSet());
-
- // check percentage
- if (usedPercentage < 100 && noWeightAttributes.isEmpty()) {
- throw new IllegalArgumentException("Used percentage is less than 100");
- }
-
- // split remaining weight
- int num = noWeightAttributes.size();
- double percentage = (100 - usedPercentage) / num;
- for (AppraiseAttribute attr : noWeightAttributes) {
- attr.setWeight(percentage);
- usedPercentage += percentage;
- }
-
- // registry
- registry.getAppraiseTypeKeys().put(key, this);
- registry.getAppraiseTypes().add(this);
-
- // unmodifiable
- attributes = Collections.unmodifiableSet(attributes);
- validMaterials = Collections.unmodifiableSet(validMaterials);
- validEquipmentSlots = Collections.unmodifiableSet(validEquipmentSlots);
- validSlimefunItemIds = Collections.unmodifiableSet(validSlimefunItemIds);
-
- this.addon = addon;
-
- return this;
- }
-
- /**
- * Returns if this {@link AppraiseType} has been registered.
- *
- * @return if this {@link AppraiseType} has been registered.
- */
- public final boolean isRegistered() {
- return addon != null;
- }
-
- /**
- * Check if this {@link AppraiseType} is registered.
- *
- * @throws IllegalStateException if this {@link AppraiseType} is registered.
- */
- protected final void checkState() {
- if (isRegistered()) {
- throw new IllegalStateException("This appraise type is already registered");
- }
- }
-
- /**
- * This method checks if specified {@link ItemStack} fit this {@link AppraiseType}.
- *
- * @param itemStack The {@link ItemStack} to be checked.
- *
- * @return If the {@link ItemStack} fit this {@link AppraiseType}.
- */
- public boolean isValidItem(@Nonnull ItemStack itemStack) {
- // Material check
- if (checkMaterial() && !validMaterials.contains(itemStack.getType())) {
- return false;
- }
-
- // Equipment type check
- Optional sfItem = Optional.ofNullable(SlimefunItem.getByItem(itemStack));
- return switch (getEquipmentType()) {
- case VANILLA -> sfItem.isEmpty();
- case SLIMEFUN -> sfItem.isPresent() && isAcceptableSlimefunItem(sfItem.get());
- case ANY -> sfItem.isEmpty() || isAcceptableSlimefunItem(sfItem.get());
- };
- }
-
- /**
- * This is the default method to check if a {@link SlimefunItem} fit this {@link AppraiseType}.
- *
- * @param sfItem The {@link SlimefunItem} to be checked.
- *
- * @return If the {@link SlimefunItem} fit this {@link AppraiseType}.
- */
- public boolean isAcceptableSlimefunItem(@Nonnull SlimefunItem sfItem) {
- String id = sfItem.getId();
- return validSlimefunItemIds.isEmpty() || validSlimefunItemIds.contains(id);
- }
-
- @Override
- public final boolean equals(Object obj) {
- if (obj instanceof AppraiseType other) {
- return this.getKey().equals(other.getKey());
- } else {
- return false;
- }
- }
-
- @Override
- public final int hashCode() {
- return getKey().hashCode();
- }
-
- @Nonnull
- @Override
- public String toString() {
- return "AppraiseType[" + getKey() + "]";
- }
-
- /**
- * This method will generate random values as {@link AppraiseResult}.
- *
- * @return The {@link AppraiseResult}.
- */
- @Nonnull
- public AppraiseResult appraise() {
- AppraiseResult.Builder builder = new AppraiseResult.Builder(this);
-
- for (AppraiseAttribute attr : attributes) {
- double value = RandomUtil.randomDouble(attr.getMin(), attr.getMax());
- builder.add(attr, value);
- }
-
- return builder.build();
- }
-
- /**
- * This enum holds the acceptable type of appraisable items.
- */
- public enum EquipmentType {
- /**
- * Any vanilla or slimefun item is acceptable.
- */
- ANY,
-
- /**
- * Only Slimefun items are acceptable.
- */
- SLIMEFUN,
-
- /**
- * Only vanilla items are acceptable.
- */
- VANILLA
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/AppraiseTypeKeyConflictException.java b/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/AppraiseTypeKeyConflictException.java
deleted file mode 100644
index 707f5407..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/AppraiseTypeKeyConflictException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.github.slimefunguguproject.bump.api.exceptions;
-
-import java.io.Serial;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.NamespacedKey;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-
-/**
- * An {@link AppraiseTypeKeyConflictException} is thrown whenever two {@link AppraiseType}
- * are trying to register with same {@link NamespacedKey}.
- *
- * @author ybw0014
- */
-public class AppraiseTypeKeyConflictException extends RuntimeException {
-
- @Serial
- private static final long serialVersionUID = -1145141919810L;
-
- /**
- * Constructs a new {@link AppraiseTypeKeyConflictException} with given {@link AppraiseType}.
- *
- * @param type1 The first {@link AppraiseType} with this {@link NamespacedKey}.
- * @param type2 The second {@link AppraiseType} with this {@link NamespacedKey}.
- */
- @ParametersAreNonnullByDefault
- public AppraiseTypeKeyConflictException(AppraiseType type1, AppraiseType type2) {
- super("Two appraise types have conflicting NamespacedKey: " + type1 + " and " + type2);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.java b/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.java
deleted file mode 100644
index 87d490e4..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.github.slimefunguguproject.bump.api.exceptions;
-
-import java.io.Serial;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.NamespacedKey;
-
-import io.github.slimefunguguproject.bump.utils.tags.BumpTag;
-
-/**
- * A {@link TagMisconfigurationException} is thrown whenever a {@link BumpTag}
- * contains illegal, invalid or unknown values.
- *
- * @author TheBusyBiscuit
- * @author ybw0014
- */
-public class TagMisconfigurationException extends Exception {
-
- @Serial
- private static final long serialVersionUID = 1145141919810L;
-
- /**
- * This constructs a new {@link TagMisconfigurationException} for the given
- * {@link }'s {@link NamespacedKey} with the provided context.
- *
- * @param key The {@link NamespacedKey} of {@link BumpTag}
- * @param message The message to display
- */
- @ParametersAreNonnullByDefault
- public TagMisconfigurationException(NamespacedKey key, String message) {
- super("Tag '" + key + "' has been misconfigured: " + message);
- }
-
- /**
- * This constructs a new {@link io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException} for the given
- * {@link BumpTag}'s {@link NamespacedKey} with the provided context.
- *
- * @param key The {@link NamespacedKey} of {@link BumpTag}
- * @param cause The {@link Throwable} which has caused this to happen
- */
- @ParametersAreNonnullByDefault
- public TagMisconfigurationException(NamespacedKey key, Throwable cause) {
- super("Tag '" + key + "' has been misconfigured (" + cause.getMessage() + ')', cause);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/package-info.java b/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/package-info.java
deleted file mode 100644
index fc5865ff..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/exceptions/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * This package contains exceptions.
- */
-package io.github.slimefunguguproject.bump.api.exceptions;
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/items/LocalizedItemStack.java b/src/main/java/io/github/slimefunguguproject/bump/api/items/LocalizedItemStack.java
deleted file mode 100644
index 35f7a203..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/items/LocalizedItemStack.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.github.slimefunguguproject.bump.api.items;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.core.services.LocalizationService;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-
-import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil;
-
-/**
- * This is an extended {@link SlimefunItemStack} that loads name and lore
- * from {@link LocalizationService} in Bump.
- *
- * @author ybw0014
- */
-public class LocalizedItemStack extends SlimefunItemStack {
- @ParametersAreNonnullByDefault
- public LocalizedItemStack(String id, Material material) {
- super(
- id,
- material,
- Bump.getLocalization().getItemName(id),
- Bump.getLocalization().getItemLore(id)
- );
- }
-
- @ParametersAreNonnullByDefault
- public LocalizedItemStack(String id, Material material, String... appendLore) {
- super(
- id,
- material,
- Bump.getLocalization().getItemName(id),
- Bump.getLocalization().getItemLore(id)
- );
-
- appendLore(appendLore);
- }
-
- @ParametersAreNonnullByDefault
- public LocalizedItemStack(String id, String texture) {
- super(
- id,
- texture,
- Bump.getLocalization().getItemName(id),
- Bump.getLocalization().getItemLore(id)
- );
- }
-
- @ParametersAreNonnullByDefault
- public LocalizedItemStack(String id, String texture, String... appendLore) {
- super(
- id,
- texture,
- Bump.getLocalization().getItemName(id),
- Bump.getLocalization().getItemLore(id)
- );
-
- appendLore(appendLore);
- }
-
- private void appendLore(String... lores) {
- ItemMeta im = getItemMeta();
- List lore;
- if (im.hasLore()) {
- lore = im.getLore();
- } else {
- lore = new ArrayList<>();
- }
- for (String line : lores) {
- lore.add(ChatUtil.color(line));
- }
- im.setLore(lore);
- setItemMeta(im);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/items/package-info.java b/src/main/java/io/github/slimefunguguproject/bump/api/items/package-info.java
deleted file mode 100644
index 9068959c..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/items/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * This package contains classes about items.
- */
-package io.github.slimefunguguproject.bump.api.items;
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/package-info.java b/src/main/java/io/github/slimefunguguproject/bump/api/package-info.java
deleted file mode 100644
index e6baecb0..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/api/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * This package contains classes and sub-packages related to the interaction with Bump via API.
- */
-package io.github.slimefunguguproject.bump.api;
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/BumpRegistry.java b/src/main/java/io/github/slimefunguguproject/bump/core/BumpRegistry.java
deleted file mode 100644
index 10c8838e..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/BumpRegistry.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package io.github.slimefunguguproject.bump.core;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.NamespacedKey;
-import org.bukkit.plugin.java.JavaPlugin;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * This class holds {@link Map Maps} and {@link List Lists} related to Bump.
- *
- * @author ybw0014
- */
-public final class BumpRegistry {
- // config
- @Getter
- private final AddonConfig config;
-
- // appraise
- @Getter
- private final Map appraiseTypeKeys = new HashMap<>();
- @Getter
- private final Set appraiseTypes = new HashSet<>();
- @Getter
- private final Map starThresholds = new LinkedHashMap<>();
-
- // language
- @Getter
- @Setter
- private String language;
-
- @ParametersAreNonnullByDefault
- public BumpRegistry(JavaPlugin plugin, AddonConfig config) {
- this.config = config;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.java b/src/main/java/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.java
deleted file mode 100644
index 6d7d69f7..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.github.slimefunguguproject.bump.core.attributes;
-
-import io.github.slimefunguguproject.bump.implementation.items.machines.AppraisalInstrument;
-import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute;
-
-/**
- * This {@link ItemAttribute} indicates that this item can be appraised.
- *
- * Implement this interface if the item can be appraised in {@link AppraisalInstrument} directly.
- *
- * @author ybw0014
- */
-public interface AppraisableItem extends ItemAttribute {
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.java b/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.java
deleted file mode 100644
index ed71af9a..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package io.github.slimefunguguproject.bump.core.attributes;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.utils.ValidateUtils;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-/**
- * This {@link ItemAttribute} indicates that this item has cooldown time.
- *
- * @author ybw0014
- */
-public interface CooldownItem extends ItemAttribute {
- /**
- * This method returns the cooldown time in seconds.
- *
- * @return cooldown time in seconds.
- */
- int getCooldown();
-
- default void setCooldown(@Nonnull ItemStack itemStack) {
- if (ValidateUtils.noAirItem(itemStack)) {
- ItemMeta im = itemStack.getItemMeta();
- PersistentDataAPI.setLong(im, Keys.LAST_USED, System.currentTimeMillis());
- itemStack.setItemMeta(im);
- }
- }
-
- /**
- * This method checks if given {@link ItemStack} has cooled down.
- *
- * @param itemStack The {@link ItemStack} to be checked
- *
- * @return if the item can be used now
- */
- default boolean isCooldown(@Nonnull ItemStack itemStack) {
- if (ValidateUtils.noAirItem(itemStack)) {
- ItemMeta im = itemStack.getItemMeta();
-
- if (PersistentDataAPI.hasLong(im, Keys.LAST_USED)) {
- long lastUsed = PersistentDataAPI.getLong(im, Keys.LAST_USED);
-
- return lastUsed + getCooldown() * 1000L < System.currentTimeMillis();
- } else {
- return true;
- }
- } else {
- return false;
- }
- }
-
- default boolean checkCooldown(@Nonnull ItemStack itemStack) {
- if (ValidateUtils.noAirItem(itemStack)) {
- if (isCooldown(itemStack)) {
- setCooldown(itemStack);
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.java b/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.java
deleted file mode 100644
index 3ab1da20..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package io.github.slimefunguguproject.bump.core.attributes;
-
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.GameMode;
-import org.bukkit.entity.Player;
-import org.bukkit.event.entity.FoodLevelChangeEvent;
-
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
-import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute;
-
-/**
- * This {@link ItemAttribute} indicates that the item will cost hunger when using.
- *
- * @author ybw0014
- */
-@SuppressWarnings("ConstantConditions")
-public interface CostHungerItem extends ItemAttribute {
- /**
- * This method returns the {@link ItemSetting} of hunger cost.
- *
- * @return the {@link ItemSetting} of hunger cost
- */
- ItemSetting getHungerCostSetting();
-
- /**
- * This method returns the hunger cost from {@link ItemSetting}.
- *
- * @return the hunger cost
- */
- default int getHungerCost() {
- return getHungerCostSetting().getValue();
- }
-
- /**
- * This method will check whether {@link Player}'s food level is sufficient to cost.
- *
- * @param p the {@link Player} that uses the item
- *
- * @return if player has enough hunger
- */
- default boolean checkHunger(@Nonnull Player p) {
- Preconditions.checkArgument(p != null, "player cannot be null");
-
- if (p.getGameMode() != GameMode.CREATIVE) {
- return p.getFoodLevel() >= getHungerCost();
- } else {
- return true;
- }
- }
-
- /**
- * This method will cost hunger of a {@link Player}.
- *
- * It will call {@link FoodLevelChangeEvent} and cost {@link Player}'s
- * hunger if {@link Player}'s {@link GameMode} is not creative and
- * the event is not cancelled.
- *
- * @param p the {@link Player} that uses the item
- *
- * @return if player has reduced enough hunger
- */
- default boolean costHunger(@Nonnull Player p) {
- Preconditions.checkArgument(p != null, "player cannot be null");
-
- if (checkHunger(p)) {
- return FoodLevelUtils.set(p, p.getFoodLevel() - getHungerCost());
- } else {
- return false;
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.java b/src/main/java/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.java
deleted file mode 100644
index 379eb7d9..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.github.slimefunguguproject.bump.core.handlers;
-
-import java.util.Optional;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.entity.EntityShootBowEvent;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.listeners.BowShootListener;
-import io.github.thebusybiscuit.slimefun4.api.exceptions.IncompatibleItemHandlerException;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemHandler;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-
-/**
- * This {@link ItemHandler} is triggered when a player right click with a bow.
- *
- * @author ybw0014
- * @see BowShootListener
- */
-public interface BowUseHandler extends ItemHandler {
-
- void onUse(EntityShootBowEvent e, Player p, ItemStack bow);
-
- @Nonnull
- @Override
- default Optional validate(SlimefunItem item) {
- if (item.getItem().getType() != Material.BOW) {
- return Optional.of(new IncompatibleItemHandlerException("Only bows can have a BowUseHandler.", item, this));
- }
-
- return Optional.empty();
- }
-
- @Nonnull
- @Override
- default Class extends ItemHandler> getIdentifier() {
- return BowUseHandler.class;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/recipes/BumpRecipeTypes.java b/src/main/java/io/github/slimefunguguproject/bump/core/recipes/BumpRecipeTypes.java
deleted file mode 100644
index 1c4d5191..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/recipes/BumpRecipeTypes.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.slimefunguguproject.bump.core.recipes;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class holds all {@link RecipeType} of Bump.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class BumpRecipeTypes {
- public static final RecipeType GETGOLD_SPADE = new RecipeType(
- Bump.createKey("getgold_spade"),
- BumpItems.GETGOLD_SPADE
- );
-
- public static final RecipeType COMPRESSOR_MOCK = new RecipeType(
- Bump.createKey("compressor_mock"),
- Bump.getLocalization().getRecipeTypeItem(
- "compressor_mock",
- SlimefunItems.COMPRESSOR
- )
- );
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/services/ConfigUpdateService.java b/src/main/java/io/github/slimefunguguproject/bump/core/services/ConfigUpdateService.java
deleted file mode 100644
index e48f80c6..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/services/ConfigUpdateService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.slimefunguguproject.bump.core.services;
-
-import javax.annotation.Nonnull;
-
-import io.github.slimefunguguproject.bump.utils.ConfigUtils;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-
-/**
- * This service will update config when there is a new version.
- *
- * @author ybw0014
- */
-public final class ConfigUpdateService {
- private static final int CURRENT_VERSION = 4;
-
- public ConfigUpdateService(@Nonnull AddonConfig config) {
- if (config.getInt("version", 1) < CURRENT_VERSION) {
- ConfigUtils.addMissingOptions(config);
- config.set("version", CURRENT_VERSION);
- config.save();
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/services/LocalizationService.java b/src/main/java/io/github/slimefunguguproject/bump/core/services/LocalizationService.java
deleted file mode 100644
index bd552b3e..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/services/LocalizationService.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package io.github.slimefunguguproject.bump.core.services;
-
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Material;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.bakedlibs.dough.items.CustomItemStack;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
-
-import net.guizhanss.guizhanlib.localization.Localization;
-import net.guizhanss.guizhanlib.localization.MinecraftLocalization;
-import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil;
-import net.guizhanss.guizhanlib.utils.StringUtil;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.TextComponent;
-
-/**
- * This is an extended {@link Localization} service made for Bump.
- *
- * @author ybw0014
- */
-@SuppressWarnings({"ConstantConditions", "java:S1192"})
-public final class LocalizationService extends MinecraftLocalization {
- private static final String NULL_RECIPE_TYPE_MESSAGE = "RecipeType Id cannot be null";
-
- public LocalizationService(Bump plugin) {
- super(plugin);
- }
-
- @ParametersAreNonnullByDefault
- @Nonnull
- public String getString(String key, Object... args) {
- return MessageFormat.format(getString(key), args);
- }
-
- @Nonnull
- public String getCategoryName(@Nonnull String categoryId) {
- Preconditions.checkArgument(categoryId != null, "Category Id cannot be null");
-
- return getString("categories." + StringUtil.dehumanize(categoryId).toLowerCase(Locale.ROOT));
- }
-
- @Nonnull
- public String getItemName(@Nonnull String itemId) {
- Preconditions.checkArgument(itemId != null, "Item Id cannot be null");
-
- return getString("items." + StringUtil.dehumanize(itemId).toLowerCase(Locale.ROOT) + ".name");
- }
-
- @Nonnull
- public String[] getItemLore(@Nonnull String itemId) {
- Preconditions.checkArgument(itemId != null, "Item Id cannot be null");
-
- return getStringArray("items." + StringUtil.dehumanize(itemId).toLowerCase(Locale.ROOT) + ".lore");
- }
-
- @Nonnull
- public String getResearchName(@Nonnull String researchId) {
- Preconditions.checkArgument(researchId != null, "Research Id cannot be null");
-
- return getString("researches." + StringUtil.dehumanize(researchId).toLowerCase(Locale.ROOT));
- }
-
- @ParametersAreNonnullByDefault
- @Nonnull
- public ItemStack getRecipeTypeItem(String recipeTypeId, Material material) {
- Preconditions.checkArgument(recipeTypeId != null, NULL_RECIPE_TYPE_MESSAGE);
- Preconditions.checkArgument(material != null, "Material cannot be null");
-
- recipeTypeId = StringUtil.dehumanize(recipeTypeId).toLowerCase(Locale.ROOT);
-
- return new CustomItemStack(
- material,
- getString("recipes." + recipeTypeId + ".name"),
- getStringArray("recipes." + recipeTypeId + ".lore")
- );
- }
-
- @ParametersAreNonnullByDefault
- @Nonnull
- public ItemStack getRecipeTypeItem(String recipeTypeId, String texture) {
- Preconditions.checkArgument(recipeTypeId != null, NULL_RECIPE_TYPE_MESSAGE);
- Preconditions.checkArgument(texture != null, "Texture cannot be null");
-
- recipeTypeId = StringUtil.dehumanize(recipeTypeId).toLowerCase(Locale.ROOT);
-
- return new CustomItemStack(
- SlimefunUtils.getCustomHead(texture),
- getString("recipes." + recipeTypeId + ".name"),
- getStringArray("recipes." + recipeTypeId + ".lore")
- );
- }
-
- @ParametersAreNonnullByDefault
- @Nonnull
- public ItemStack getRecipeTypeItem(String recipeTypeId, ItemStack itemStack) {
- Preconditions.checkArgument(recipeTypeId != null, NULL_RECIPE_TYPE_MESSAGE);
- Preconditions.checkArgument(itemStack != null, "ItemStack cannot be null");
-
- recipeTypeId = StringUtil.dehumanize(recipeTypeId).toLowerCase(Locale.ROOT);
-
- return new CustomItemStack(
- itemStack,
- getString("recipes." + recipeTypeId + ".name"),
- getStringArray("recipes." + recipeTypeId + ".lore")
- );
- }
-
- @ParametersAreNonnullByDefault
- public void sendMessage(CommandSender sender, String messageKey, Object... args) {
- Preconditions.checkArgument(sender != null, "CommandSender cannot be null");
- Preconditions.checkArgument(messageKey != null, "Message key cannot be null");
-
- ChatUtil.send(sender, MessageFormat.format(getString("messages." + messageKey), args));
- }
-
- @ParametersAreNonnullByDefault
- public void sendActionbarMessage(Player p, String messageKey, Object... args) {
- Preconditions.checkArgument(p != null, "Player cannot be null");
- Preconditions.checkArgument(messageKey != null, "Message key cannot be null");
-
- String message = MessageFormat.format(getString("messages." + messageKey), args);
-
- BaseComponent[] components = TextComponent.fromLegacyText(ChatUtil.color(message));
- p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components);
- }
-
- @ParametersAreNonnullByDefault
- public void log(Level level, String key, Object... args) {
- Preconditions.checkArgument(level != null, "Log level cannot be null");
- Preconditions.checkArgument(key != null, "Key cannot be null");
-
- String message = MessageFormat.format(getString("console." + key), args);
-
- Bump.log(level, message);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.java b/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.java
deleted file mode 100644
index 088f99fb..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.github.slimefunguguproject.bump.core.services.sounds;
-
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Location;
-import org.bukkit.Sound;
-import org.bukkit.SoundCategory;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-/**
- * This enum contains almost all configurable sounds in Bump.
- */
-@Getter
-@RequiredArgsConstructor
-@SuppressWarnings("ConstantConditions")
-public enum BumpSound {
- APPRAISAL_INSTRUMENT_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F),
- APPRAISAL_INSTRUMENT_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0F, 1.0F),
- APPRAISE_TYPE_SELECT(Sound.ENTITY_ARROW_HIT_PLAYER, 1.0F, 1.0F),
- APPRAISE_TYPE_SELECTOR_OPEN(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1.0F, 1.0F),
- ATTRIBUTE_GRINDSTONE_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F),
- ATTRIBUTE_GRINDSTONE_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0F, 1.0F),
- QUALITY_IDENTIFIER_OPEN(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1.0F, 1.0F),
- QUALITY_IDENTIFIER_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F),
- QUALITY_IDENTIFIER_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0F, 1.0F),
- DEVIL_SWORD_USE(Sound.ENTITY_BLAZE_SHOOT, 1.0F, 1.0F),
- SKY_SWORD_USE(Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0F),
- SOUL_SWORD_USE(Sound.AMBIENT_CAVE, 1.0F, 1.0F),
- WITHER_SKULL_BOW_USE(Sound.ENTITY_WITHER_SHOOT, 1.0F, 1.0F);
-
- private final String sound;
- private final float volume;
- private final float pitch;
-
- BumpSound(@Nonnull Sound sound, float volume, float pitch) {
- Preconditions.checkArgument(sound != null, "Sound cannot be null");
-
- this.sound = sound.getKey().getKey();
- this.volume = volume;
- this.pitch = pitch;
- }
-
- @Nullable
- private SoundConfig getSoundConfig() {
- SoundConfig config = Bump.getSoundService().getSoundConfig(this);
-
- if (config == null) {
- Bump.getLocalization().log(Level.WARNING, "invalid-sound-config", name());
- }
-
- return config;
- }
-
- /**
- * Play this {@link BumpSound} at {@link Player}'s eye location.
- *
- * @param p The {@link Player} which to play the {@link BumpSound} to.
- */
- public void playFor(@Nonnull Player p) {
- Preconditions.checkArgument(p != null, "Player cannot be null.");
-
- SoundConfig config = getSoundConfig();
-
- if (config != null) {
- p.playSound(p.getEyeLocation(), config.sound(), SoundCategory.PLAYERS, config.volume(), config.pitch());
- }
- }
-
- /**
- * Play this {@link BumpSound} at the given {@link Location} using the
- * provided {@link SoundCategory}.
- *
- * @param loc The {@link Location} at which to play the {@link BumpSound}.
- * @param category The {@link SoundCategory} that should be used.
- */
- public void playAt(@Nonnull Location loc, @Nonnull SoundCategory category) {
- Preconditions.checkArgument(loc != null, "The location cannot be null.");
-
- SoundConfig config = getSoundConfig();
-
- if (config != null) {
- loc.getWorld().playSound(loc, config.sound(), category, config.volume(), config.pitch());
- }
- }
-
- /**
- * Play this {@link BumpSound} at the given {@link Block}.
- *
- * @param block The {@link Block} at which to play the {@link BumpSound}.
- */
- public void playAt(@Nonnull Block block) {
- Preconditions.checkArgument(block != null, "The block cannot be null.");
-
- playAt(block.getLocation(), SoundCategory.BLOCKS);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.java b/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.java
deleted file mode 100644
index 6074ba4f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.github.slimefunguguproject.bump.core.services.sounds;
-
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
-
-/**
- * A wrapper of sound configuration.
- *
- * @author ybw0014
- */
-record SoundConfig(@Nonnull String sound, float volume, float pitch) {
- public SoundConfig {
- Preconditions.checkArgument(sound != null, "Sound cannot be null");
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.java b/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.java
deleted file mode 100644
index c4bbbbd9..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package io.github.slimefunguguproject.bump.core.services.sounds;
-
-import java.util.EnumMap;
-import java.util.Map;
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-
-/**
- * This service manages all sounds used in Bump.
- *
- * @author ybw0014
- */
-public final class SoundService {
-
- private final AddonConfig config;
-
- private final Map soundMap = new EnumMap<>(BumpSound.class);
-
- /**
- * Initialize {@link SoundService}.
- *
- * @param soundConfig The config file of sounds.
- */
- public SoundService(@Nonnull AddonConfig soundConfig) {
- this.config = soundConfig;
- }
-
- /**
- * Load the configurations of all {@link BumpSound}.
- *
- * @param saveConfig Whether to save config after loading.
- */
- public void load(boolean saveConfig) {
- config.reload();
-
- for (BumpSound sound : BumpSound.values()) {
- try {
- loadSound(sound);
- } catch (Exception ex) {
- Bump.getLocalization().log(Level.SEVERE, "error-sound", sound.name());
- }
- }
-
- if (saveConfig) {
- config.save();
- }
- }
-
- /**
- * Get the {@link SoundConfig} for a specified {@link BumpSound}.
- *
- * @param sound The {@link BumpSound} to get {@link SoundConfig} for.
- *
- * @return The {@link SoundConfig} for the {@link BumpSound}. {@code null} if not exists.
- */
- @Nullable
- public SoundConfig getSoundConfig(@Nonnull BumpSound sound) {
- Preconditions.checkArgument(sound != null, "BumpSound cannot be null");
-
- return soundMap.get(sound);
- }
-
- private void loadSound(@Nonnull BumpSound sound) {
- setDefault(sound.name() + ".sound", sound.getSound());
- setDefault(sound.name() + ".volume", sound.getVolume());
- setDefault(sound.name() + ".pitch", sound.getPitch());
-
- String soundId = config.getString(sound.name() + ".sound");
- float volume = (float) config.getDouble(sound.name() + ".volume");
- float pitch = (float) config.getDouble(sound.name() + ".pitch");
-
- if (volume < 0) {
- Bump.getLocalization().log(Level.WARNING, "invalid-sound-volume", sound.name(), volume, 0.0F);
- volume = 0;
- }
-
- if (pitch < 0.5F) {
- Bump.getLocalization().log(Level.WARNING, "invalid-sound-pitch", sound.name(), volume, 0.5F);
- pitch = 0.5F;
- }
-
- SoundConfig soundConfig = new SoundConfig(soundId, volume, pitch);
- soundMap.put(sound, soundConfig);
- }
-
- @ParametersAreNonnullByDefault
- private void setDefault(String path, Object value) {
- if (!config.contains(path)) {
- config.set(path, value);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/Bump.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/Bump.java
deleted file mode 100644
index ccb87098..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/Bump.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Bukkit;
-import org.bukkit.plugin.Plugin;
-
-import io.github.slimefunguguproject.bump.core.BumpRegistry;
-import io.github.slimefunguguproject.bump.core.services.ConfigUpdateService;
-import io.github.slimefunguguproject.bump.core.services.LocalizationService;
-import io.github.slimefunguguproject.bump.core.services.sounds.SoundService;
-import io.github.slimefunguguproject.bump.implementation.setup.AppraiseSetup;
-import io.github.slimefunguguproject.bump.implementation.setup.ItemGroupsSetup;
-import io.github.slimefunguguproject.bump.implementation.setup.ItemsSetup;
-import io.github.slimefunguguproject.bump.implementation.setup.ListenerSetup;
-import io.github.slimefunguguproject.bump.implementation.setup.ResearchSetup;
-import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask;
-import io.github.slimefunguguproject.bump.utils.WikiUtils;
-import io.github.slimefunguguproject.bump.utils.tags.BumpTag;
-import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AbstractAddon;
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-import net.guizhanss.guizhanlib.updater.GuizhanBuildsUpdater;
-
-import org.bstats.bukkit.Metrics;
-import org.bstats.charts.SimplePie;
-
-/**
- * Main class for {@link Bump}.
- *
- * @author ybw0014
- */
-public final class Bump extends AbstractAddon {
-
- private static final String DEFAULT_LANG = "en-US";
-
- // localization
- private LocalizationService localization;
-
- // registry
- private BumpRegistry registry;
-
- // services
- private SoundService soundService;
-
- public Bump() {
- super("SlimefunGuguProject", "Bump", "main", "options.auto-update");
- }
-
- @Nonnull
- private static Bump inst() {
- return getInstance();
- }
-
- @Nonnull
- public static LocalizationService getLocalization() {
- return inst().localization;
- }
-
- @Nonnull
- public static BumpRegistry getRegistry() {
- return inst().registry;
- }
-
- @Nonnull
- public static SoundService getSoundService() {
- return inst().soundService;
- }
-
- @Override
- public void enable() {
- sendConsole("&6&l _____");
- sendConsole("&6&l /\\ _`\\ ");
- sendConsole("&6&l \\ \\ \\L\\ \\ __ __ ___ ___ _____ ");
- sendConsole("&6&l \\ \\ _ <'/\\ \\/\\ \\ /' __` __`\\/\\ '__`\\ ");
- sendConsole("&6&l \\ \\ \\L\\ \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\L\\ \\");
- sendConsole("&6&l \\ \\____/\\ \\____/\\ \\_\\ \\_\\ \\_\\ \\ ,__/");
- sendConsole("&6&l \\/___/ \\/___/ \\/_/\\/_/\\/_/\\ \\ \\/ ");
- sendConsole("&6&l \\ \\_\\ ");
- sendConsole("&6&l \\/_/ ");
- sendConsole("&a&l Bump 2 for Slimefun4 RC-30+");
- sendConsole("&a&l Powered By bxx2004, SlimefunGuguProject");
- sendConsole("&a&l GitHub: https://github.com/SlimefunGuguProject/Bump");
- sendConsole("&a&l Issues: https://github.com/SlimefunGuguProject/Bump/issues");
-
- // config
- AddonConfig config = getAddonConfig();
- new ConfigUpdateService(config);
-
- // registry
- registry = new BumpRegistry(this, config);
-
- // localization
- log(Level.INFO, "Loading language...");
- String lang = config.getString("options.lang", DEFAULT_LANG);
- localization = new LocalizationService(this);
- localization.addLanguage(lang);
- getRegistry().setLanguage(lang);
- if (!lang.equals(DEFAULT_LANG)) {
- localization.addLanguage(DEFAULT_LANG);
- }
- log(Level.INFO, "Loaded language {0}", lang);
-
- // check slimefun version
- Slimefun slimefun = Slimefun.instance();
- if (slimefun != null && isSCSlimefun(slimefun.getPluginVersion())
- && lang.equalsIgnoreCase(DEFAULT_LANG) && !lang.startsWith("zh-")
- ) {
- log(Level.WARNING, "你似乎正在使用汉化版粘液科技,但未设置Bump的语言。");
- log(Level.WARNING, "Bump是一个支持多语言的粘液附属,默认语言为英文。");
- log(Level.WARNING, "你需要在 /plugins/Bump/config.yml 中,");
- log(Level.WARNING, "设置 options.lang 为 zh-CN 来将Bump的语言改为简体中文。");
- }
-
- // tags
- BumpTag.reloadAll();
-
- // sound service
- soundService = new SoundService(new AddonConfig("sounds.yml"));
- soundService.load(true);
-
- // appraise setup
- AppraiseSetup.setupTypes();
- AppraiseSetup.setupStars();
-
- // item groups setup
- ItemGroupsSetup.setup(this);
-
- // items setup
- ItemsSetup.setup(this);
-
- // researches setup
- boolean enableResearch = config.getBoolean("options.enable-research", true);
- if (enableResearch) {
- ResearchSetup.setup();
- }
-
- // wiki setup
- WikiUtils.setupJson();
-
- // listeners
- ListenerSetup.setup(this);
-
- // tasks
- WeaponProjectileTask.start();
-
- // Metrics setup
- final Metrics metrics = new Metrics(this, 14870);
- metrics.addCustomChart(new SimplePie("server_language", () -> lang));
- metrics.addCustomChart(new SimplePie("enable_research", () -> enableResearch ? "enabled" : "disabled"));
- }
-
- @Override
- public void disable() {
- Bukkit.getScheduler().cancelTasks(this);
- }
-
- @Override
- protected void autoUpdate() {
- try {
- // use updater in lib plugin
- Class> clazz = Class.forName("net.guizhanss.guizhanlibplugin.updater.GuizhanUpdater");
- Method updaterStart = clazz.getDeclaredMethod("start", Plugin.class, File.class, String.class, String.class, String.class);
- updaterStart.invoke(null, this, getFile(), getGithubUser(), getGithubRepo(), getGithubBranch());
- } catch (Exception ignored) {
- // use updater in lib
- new GuizhanBuildsUpdater(this, getFile(), getGithubUser(), getGithubRepo(), getGithubBranch()).start();
- }
- }
-
- @Nonnull
- public String getWikiURL() {
- return "https://slimefun-addons-wiki.guizhanss.cn/bump/{0}";
- }
-
- private boolean isSCSlimefun(@Nonnull String sfVersion) {
- return sfVersion.endsWith("-canary") || sfVersion.endsWith("-release") || sfVersion.endsWith("-Beta") || sfVersion.endsWith("-Insider");
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/BumpItems.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/BumpItems.java
deleted file mode 100644
index ba7d5ffe..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/BumpItems.java
+++ /dev/null
@@ -1,311 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation;
-
-import org.bukkit.Material;
-import org.bukkit.enchantments.Enchantment;
-
-import io.github.slimefunguguproject.bump.api.items.LocalizedItemStack;
-import io.github.slimefunguguproject.bump.implementation.items.machines.AppraisalInstrument;
-import io.github.slimefunguguproject.bump.implementation.items.machines.AttributeGrindstone;
-import io.github.slimefunguguproject.bump.implementation.items.tools.QualityIdentifier;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.Utils;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class holds all {@link SlimefunItemStack} of Bump.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class BumpItems {
- public static final SlimefunItemStack RANDOM_HELMET;
- public static final SlimefunItemStack RANDOM_HORSE_ARMOR;
- public static final SlimefunItemStack XUEBI;
- public static final SlimefunItemStack KELE;
- public static final SlimefunItemStack FANGBIANMIAN;
- public static final SlimefunItemStack LATIAO;
- public static final SlimefunItemStack KOUXIANGTANG;
- public static final SlimefunItemStack ZONGZI;
- public static final SlimefunItemStack APPRAISAL;
- public static final SlimefunItemStack ATTRIBUTE_GRINDSTONE;
- public static final SlimefunItemStack SUN_ENERGY;
- public static final SlimefunItemStack MECHA_GEAR;
- public static final SlimefunItemStack OLD_COIN;
- public static final SlimefunItemStack MAKE;
- public static final SlimefunItemStack OLD_CPU;
- public static final SlimefunItemStack CPU;
- public static final SlimefunItemStack SOUL_PAPER;
- public static final SlimefunItemStack KSF_STUFF;
- public static final SlimefunItemStack WATER_SUGAR;
- public static final SlimefunItemStack PEACH_WOOD;
- public static final SlimefunItemStack UPDATE_POWER;
- public static final SlimefunItemStack COMPRESSED_RANDOM_EQUIPMENT;
- public static final SlimefunItemStack GETGOLD_SPADE;
- public static final SlimefunItemStack QUALITY_IDENTIFIER;
- public static final SlimefunItemStack APPRAISAL_PAPER_ARMOR;
- public static final SlimefunItemStack APPRAISAL_PAPER_DAMAGE;
- public static final SlimefunItemStack APPRAISAL_PAPER_HORSE_ARMOR;
- public static final SlimefunItemStack LIGHT_BOW;
- public static final SlimefunItemStack WITHERSKULL_BOW;
- public static final SlimefunItemStack EMER_SWORD;
- public static final SlimefunItemStack BONE_SWORD;
- public static final SlimefunItemStack RANDOM_SWORD;
- public static final SlimefunItemStack GUARD_SWORD;
- public static final SlimefunItemStack PEACH_SWORD;
- public static final SlimefunItemStack SOUL_SWORD;
- public static final SlimefunItemStack SKY_SWORD;
- public static final SlimefunItemStack DEVIL_SWORD;
- public static final SlimefunItemStack SKY_DEVIL_SWORD;
-
- static {
- // region armor
- RANDOM_HELMET = new LocalizedItemStack(
- "RANDOM_HELMET",
- Material.DIAMOND_HELMET
- );
-
- RANDOM_HORSE_ARMOR = new LocalizedItemStack(
- "RANDOM_HORSE_ARMOR",
- Material.DIAMOND_HORSE_ARMOR
- );
-
- AppraiseUtils.setAppraisable(RANDOM_HELMET);
- AppraiseUtils.setAppraisable(RANDOM_HORSE_ARMOR);
- // endregion armor
-
- // region food
- XUEBI = new LocalizedItemStack(
- "XUEBI",
- Material.POTION
- );
-
- KELE = new LocalizedItemStack(
- "KELE",
- Material.POTION
- );
-
- FANGBIANMIAN = new LocalizedItemStack(
- "FANGBIANMIAN",
- Material.STRING
- );
-
- LATIAO = new LocalizedItemStack(
- "LATIAO",
- Material.ROTTEN_FLESH
- );
-
- KOUXIANGTANG = new LocalizedItemStack(
- "KOUXIANGTANG",
- Material.SUGAR
- );
-
- ZONGZI = new LocalizedItemStack(
- "ZONGZI",
- Material.GREEN_DYE
- );
-
- Utils.glowItem(XUEBI);
- // endregion food
-
- // region machine
- APPRAISAL = new LocalizedItemStack(
- "APPRAISAL",
- Material.BELL,
- LoreBuilder.power(AppraisalInstrument.ENERGY_CONSUMPTION, " " + Bump.getLocalization().getString("lores.per-use"))
- );
-
- ATTRIBUTE_GRINDSTONE = new LocalizedItemStack(
- "ATTRIBUTE_GRINDSTONE",
- Material.GRINDSTONE,
- LoreBuilder.power(AttributeGrindstone.ENERGY_CONSUMPTION, " " + Bump.getLocalization().getString("lores.per-use"))
- );
- // endregion machine
-
- // region stuff
- SUN_ENERGY = new LocalizedItemStack(
- "SUN_ENERGY",
- Material.BELL
- );
-
- MECHA_GEAR = new LocalizedItemStack(
- "MECHA_GEAR",
- Material.ENDER_PEARL
- );
-
- OLD_COIN = new LocalizedItemStack(
- "OLD_COIN",
- Material.GOLD_NUGGET
- );
-
- MAKE = new LocalizedItemStack(
- "MAKE",
- Material.DIAMOND
- );
-
- OLD_CPU = new LocalizedItemStack(
- "OLD_CPU",
- Material.PRISMARINE_CRYSTALS
- );
-
- CPU = new LocalizedItemStack(
- "CPU",
- Material.DIAMOND
- );
-
- SOUL_PAPER = new LocalizedItemStack(
- "SOUL_PAPER",
- Material.PAPER
- );
-
- KSF_STUFF = new LocalizedItemStack(
- "KSF_STUFF",
- Material.BEETROOT_SEEDS
- );
-
- WATER_SUGAR = new LocalizedItemStack(
- "WATER_SUGAR",
- Material.SUGAR
- );
-
- PEACH_WOOD = new LocalizedItemStack(
- "PEACH_WOOD",
- Material.STICK
- );
-
- UPDATE_POWER = new LocalizedItemStack(
- "UPDATE_POWER",
- Material.ZOMBIE_HEAD
- );
-
- COMPRESSED_RANDOM_EQUIPMENT = new LocalizedItemStack(
- "COMPRESSED_RANDOM_EQUIPMENT",
- "bb82d5e2033ce8d9821d53e59d480f3dd60b4f9e555f67056c938c0240e16ffe"
- );
- // endregion stuff
-
- // region tool
- GETGOLD_SPADE = new LocalizedItemStack(
- "GETGOLD_SPADE",
- Material.GOLDEN_SHOVEL
- );
-
- QUALITY_IDENTIFIER = new LocalizedItemStack(
- "QUALITY_IDENTIFIER",
- Material.PAPER,
- LoreBuilder.usesLeft(QualityIdentifier.MAX_USES)
- );
-
- APPRAISAL_PAPER_ARMOR = new LocalizedItemStack(
- "APPRAISAL_PAPER_ARMOR",
- Material.PAPER,
- LoreBuilder.usesLeft(QualityIdentifier.MAX_USES)
- );
-
- APPRAISAL_PAPER_DAMAGE = new LocalizedItemStack(
- "APPRAISAL_PAPER_DAMAGE",
- Material.PAPER,
- LoreBuilder.usesLeft(QualityIdentifier.MAX_USES)
- );
-
- APPRAISAL_PAPER_HORSE_ARMOR = new LocalizedItemStack(
- "APPRAISAL_PAPER_HORSE_ARMOR",
- Material.PAPER,
- LoreBuilder.usesLeft(QualityIdentifier.MAX_USES)
- );
-
- GETGOLD_SPADE.addUnsafeEnchantment(Enchantment.MENDING, 3);
- // endregion tool
-
- // region weapon
- LIGHT_BOW = new LocalizedItemStack(
- "LIGHT_BOW",
- Material.BOW
- );
-
- WITHERSKULL_BOW = new LocalizedItemStack(
- "WITHERSKULL_BOW",
- Material.BOW
- );
-
- EMER_SWORD = new LocalizedItemStack(
- "EMER_SWORD",
- Material.DIAMOND_SWORD
- );
-
- BONE_SWORD = new LocalizedItemStack(
- "BONE_SWORD",
- Material.WOODEN_SWORD
- );
-
- RANDOM_SWORD = new LocalizedItemStack(
- "RANDOM_SWORD",
- Material.DIAMOND_SWORD
- );
-
- GUARD_SWORD = new LocalizedItemStack(
- "GUARD_SWORD",
- Material.GOLDEN_SWORD
- );
-
- PEACH_SWORD = new LocalizedItemStack(
- "PEACH_SWORD",
- Material.WOODEN_SWORD
- );
-
- SOUL_SWORD = new LocalizedItemStack(
- "SOUL_SWORD",
- Material.IRON_SWORD
- );
-
- SKY_SWORD = new LocalizedItemStack(
- "SKY_SWORD",
- Material.GOLDEN_SWORD
- );
-
- DEVIL_SWORD = new LocalizedItemStack(
- "DEVIL_SWORD",
- Material.IRON_SWORD
- );
-
- SKY_DEVIL_SWORD = new LocalizedItemStack(
- "SKY_DEVIL_SWORD",
- Material.DIAMOND_SWORD
- );
-
- LIGHT_BOW.addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 5);
-
- WITHERSKULL_BOW.addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 5);
-
- EMER_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 1);
-
- BONE_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
-
- AppraiseUtils.setAppraisable(RANDOM_SWORD);
-
- GUARD_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 5);
- GUARD_SWORD.addUnsafeEnchantment(Enchantment.IMPALING, 3);
-
- PEACH_SWORD.addUnsafeEnchantment(Enchantment.KNOCKBACK, 5);
- PEACH_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 3);
-
- SOUL_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 2);
- SOUL_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
-
- SKY_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 1);
- SKY_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
- SKY_SWORD.addUnsafeEnchantment(Enchantment.SWEEPING_EDGE, 1);
-
- DEVIL_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 1);
- DEVIL_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
- DEVIL_SWORD.addUnsafeEnchantment(Enchantment.SWEEPING_EDGE, 1);
-
- SKY_DEVIL_SWORD.addUnsafeEnchantment(Enchantment.DAMAGE_ALL, 5);
- SKY_DEVIL_SWORD.addUnsafeEnchantment(Enchantment.DURABILITY, 5);
- SKY_DEVIL_SWORD.addUnsafeEnchantment(Enchantment.LOYALTY, 5);
-
- // endregion weapon
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.java
deleted file mode 100644
index 23cb9eb1..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.groups;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.NamespacedKey;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.menus.AppraiseTypeMenu;
-import io.github.thebusybiscuit.slimefun4.api.items.groups.FlexItemGroup;
-import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
-import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
-import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
-
-/**
- * A flex item group that displays apprase types.
- *
- * @author ybw0014
- */
-public final class AppraiseInfoGroup extends FlexItemGroup {
-
- private final String name;
-
- @ParametersAreNonnullByDefault
- public AppraiseInfoGroup(String name, NamespacedKey key, ItemStack item) {
- super(key, item);
-
- this.name = name;
- }
-
- @Override
- @ParametersAreNonnullByDefault
- public boolean isVisible(Player player, PlayerProfile playerProfile, SlimefunGuideMode guideMode) {
- return false;
- }
-
- @Override
- @ParametersAreNonnullByDefault
- public void open(Player p, PlayerProfile profile, SlimefunGuideMode mode) {
- new AppraiseInfoMenu(name, type -> {
- // open the detail menu
- new AppraiseTypeMenu(type, () -> open(p, profile, mode)).open(p);
- }, () -> {
- // back to main menu
- SlimefunGuide.openItemGroup(profile, BumpItemGroups.MAIN, mode, 1);
- }).open(p);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.java
deleted file mode 100644
index eb9aceb8..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.groups;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.bakedlibs.dough.items.CustomItemStack;
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.menus.AppraiseTypesMenu;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-
-final class AppraiseInfoMenu extends AppraiseTypesMenu {
- @ParametersAreNonnullByDefault
- public AppraiseInfoMenu(String name, Consumer successCallback, Runnable backCallback) {
- super(name, successCallback, backCallback);
- }
-
- @Nonnull
- @Override
- public ItemStack getDisplayItem(@Nonnull AppraiseType type) {
- List lore = AppraiseUtils.getDescriptionLore(type);
- lore.add("");
- lore.add(Bump.getLocalization().getString("appraise_info.click"));
-
- return new CustomItemStack(
- Material.PAPER,
- Bump.getLocalization().getString("appraise_info.name", type.getName()),
- lore
- );
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.java
deleted file mode 100644
index a4bd607f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.groups;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack;
-
-import dev.sefiraat.sefilib.slimefun.itemgroup.DummyItemGroup;
-import dev.sefiraat.sefilib.slimefun.itemgroup.SimpleFlexGroup;
-import lombok.experimental.UtilityClass;
-
-/**
- * This class holds all {@link ItemGroup}s of Bump.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class BumpItemGroups {
- public static final SimpleFlexGroup MAIN = new SimpleFlexGroup(
- Bump.getInstance(),
- Bump.getLocalization().getCategoryName("main"),
- Bump.createKey("main"),
- new CustomItemStack(
- Material.DIAMOND,
- Bump.getLocalization().getCategoryName("main")
- )
- );
-
- public static final ItemStack WIKI = new CustomItemStack(
- Material.KNOWLEDGE_BOOK,
- Bump.getLocalization().getCategoryName("wiki"),
- "",
- Bump.getLocalization().getString("lores.click-to-open")
- );
-
- public static final ItemGroup STUFF = new DummyItemGroup(
- Bump.createKey("stuff"),
- new CustomItemStack(
- Material.NETHER_STAR,
- Bump.getLocalization().getCategoryName("stuff")
- )
- );
-
- public static final ItemGroup FOOD = new DummyItemGroup(
- Bump.createKey("food"),
- new CustomItemStack(
- Material.BREAD,
- Bump.getLocalization().getCategoryName("food")
- )
- );
-
- public static final ItemGroup MACHINE = new DummyItemGroup(
- Bump.createKey("machine"),
- new CustomItemStack(
- Material.ANVIL,
- Bump.getLocalization().getCategoryName("machine")
- )
- );
-
- public static final ItemGroup TOOL = new DummyItemGroup(
- Bump.createKey("tool"),
- new CustomItemStack(
- Material.DIAMOND_PICKAXE,
- Bump.getLocalization().getCategoryName("tool")
- )
- );
-
- public static final ItemGroup ARMOR = new DummyItemGroup(
- Bump.createKey("armor"),
- new CustomItemStack(
- Material.DIAMOND,
- Bump.getLocalization().getCategoryName("armor")
- )
- );
-
- public static final ItemGroup WEAPON = new DummyItemGroup(
- Bump.createKey("weapon"),
- new CustomItemStack(
- Material.IRON_SWORD,
- Bump.getLocalization().getCategoryName("weapon")
- )
- );
-
- public static final AppraiseInfoGroup APPRAISE_INFO = new AppraiseInfoGroup(
- Bump.getLocalization().getCategoryName("appraise_info"),
- Bump.createKey("appraise_info"),
- new CustomItemStack(
- Material.NAME_TAG,
- Bump.getLocalization().getCategoryName("appraise_info")
- )
- );
-
- public static final ItemGroup HIDDEN = new DummyItemGroup(
- Bump.createKey("hidden"),
- new CustomItemStack(
- Material.BARRIER,
- "Never gonna give you up~"
- )
- );
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/HiddenItem.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/HiddenItem.java
deleted file mode 100644
index 5c705683..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/HiddenItem.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-
-/**
- * A {@link SlimefunItem} in hidden item group, usually deprecated or secret item.
- *
- * @author ybw0014
- */
-public class HiddenItem extends SlimefunItem {
- @ParametersAreNonnullByDefault
- public HiddenItem(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.HIDDEN, item, recipeType, recipe);
- }
-
- @ParametersAreNonnullByDefault
- public HiddenItem(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack output) {
- super(BumpItemGroups.HIDDEN, item, recipeType, recipe, output);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.java
deleted file mode 100644
index 4b48eaf2..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.attributes.AppraisableItem;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-
-/**
- * A {@link RandomEquipment} is an item that is an {@link AppraisableItem}.
- *
- * @author ybw0014
- */
-public final class RandomEquipment extends SlimefunItem implements AppraisableItem {
-
- @ParametersAreNonnullByDefault
- public RandomEquipment(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(itemGroup, item, recipeType, recipe);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.java
deleted file mode 100644
index 927483fe..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import java.util.Locale;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.GameMode;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.items.ItemUtils;
-
-/**
- * A {@link ConsumableFood} is a {@link SlimefunItem} that is based on vanilla food or potion.
- * Player can get effects after consuming.
- *
- * @author ybw0014
- */
-public abstract class ConsumableFood extends SimpleSlimefunItem {
-
- protected ConsumableFood(SlimefunItemStack itemStack, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.FOOD, itemStack, recipeType, recipe);
- }
-
- @Nonnull
- @Override
- public ItemConsumptionHandler getItemHandler() {
- return (e, p, item) -> {
- String messageKey = this.getId().toLowerCase(Locale.ROOT);
- Bump.getLocalization().sendActionbarMessage(p, "food." + messageKey);
-
- if (p.getGameMode() != GameMode.CREATIVE) {
- ItemUtils.consumeItem(e.getItem(), false);
- }
-
- this.applyFoodEffects(p);
- };
- }
-
- public abstract void applyFoodEffects(Player p);
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Fangbianmian.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Fangbianmian.java
deleted file mode 100644
index f28c05d6..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Fangbianmian.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * Instant noodle.
- *
- * @author ybw0014
- */
-public class Fangbianmian extends ItemFood {
-
- public Fangbianmian() {
- super(BumpItems.FANGBIANMIAN, RecipeType.MAGIC_WORKBENCH, new ItemStack[]{
- new ItemStack(Material.WATER_BUCKET), new ItemStack(Material.WATER_BUCKET), new ItemStack(Material.WATER_BUCKET),
- BumpItems.KSF_STUFF, BumpItems.KSF_STUFF, BumpItems.KSF_STUFF,
- SlimefunItems.WHEAT_FLOUR, SlimefunItems.WHEAT_FLOUR, SlimefunItems.WHEAT_FLOUR
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.set(p, 20);
- p.addPotionEffect(new PotionEffect(PotionEffectType.HEALTH_BOOST, 1500, 5));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.java
deleted file mode 100644
index f487fbc2..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import java.util.Locale;
-import java.util.UUID;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.GameMode;
-import org.bukkit.Sound;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.scheduler.BukkitRunnable;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.items.ItemUtils;
-
-import net.guizhanss.guizhanlib.common.Cooldown;
-
-/**
- * A {@link ItemFood} is a {@link SlimefunItem} that is based on a non-food item.
- * Player can get effects after consuming.
- *
- * @author ybw0014
- */
-public abstract class ItemFood extends UnplaceableBlock {
-
- private final Cooldown cooldown = new Cooldown<>();
-
- protected ItemFood(SlimefunItemStack itemStack, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.FOOD, itemStack, recipeType, recipe);
- }
-
- @Nonnull
- @Override
- public ItemUseHandler getItemHandler() {
- return e -> {
- e.cancel();
- Player p = e.getPlayer();
-
- if (!cooldown.check(p.getUniqueId())) {
- Bump.getLocalization().sendActionbarMessage(p, "food.cooldown");
- return;
- }
-
- String messageKey = getId().toLowerCase(Locale.ROOT);
- Bump.getLocalization().sendActionbarMessage(p, "food." + messageKey);
-
- if (p.getGameMode() != GameMode.CREATIVE) {
- ItemUtils.consumeItem(e.getItem(), false);
- }
-
- new BukkitRunnable() {
- int count = 7;
-
- @Override
- public void run() {
- if (count > 0) {
- p.playSound(p.getLocation(), Sound.ENTITY_GENERIC_EAT, 1, 1);
- count--;
- } else {
- cancel();
- }
- }
- }.runTaskTimer(Bump.getInstance(), 1L, 4L);
-
- applyFoodEffects(p);
- cooldown.set(p.getUniqueId(), 2000L);
- };
- }
-
- public abstract void applyFoodEffects(Player p);
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kele.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kele.java
deleted file mode 100644
index c6335144..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kele.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * Coke? Or Pepsi? Who knows.
- *
- * @author ybw0014
- */
-public class Kele extends ConsumableFood {
-
- public Kele() {
- super(BumpItems.KELE, RecipeType.MAGIC_WORKBENCH, new ItemStack[]{
- BumpItems.WATER_SUGAR, new ItemStack(Material.WATER_BUCKET), BumpItems.WATER_SUGAR,
- new ItemStack(Material.WATER_BUCKET), SlimefunItems.MAGIC_SUGAR, new ItemStack(Material.WATER_BUCKET),
- BumpItems.WATER_SUGAR, new ItemStack(Material.WATER_BUCKET), BumpItems.WATER_SUGAR
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.add(p, 6);
- p.addPotionEffect(new PotionEffect(PotionEffectType.DOLPHINS_GRACE, 2000, 5));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kouxiangtang.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kouxiangtang.java
deleted file mode 100644
index 04aaf497..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Kouxiangtang.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * Chewing gum.
- *
- * @author ybw0014
- */
-public class Kouxiangtang extends ItemFood {
-
- public Kouxiangtang() {
- super(BumpItems.KOUXIANGTANG, RecipeType.COMPRESSOR, new ItemStack[]{
- SlimefunItems.MAGIC_SUGAR
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.add(p, 6);
- p.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 1000, 5));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Latiao.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Latiao.java
deleted file mode 100644
index 5f6a1fc8..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Latiao.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * Latiao. Spicy stick.
- *
- * @author ybw0014
- */
-public class Latiao extends ConsumableFood {
-
- public Latiao() {
- super(BumpItems.LATIAO, RecipeType.COMPRESSOR, new ItemStack[]{
- SlimefunItems.WHEAT_FLOUR
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.add(p, 2);
- p.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 48, 2));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Xuebi.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Xuebi.java
deleted file mode 100644
index 2cc154bf..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Xuebi.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-
-/**
- * Sprite.
- *
- * @author ybw0014
- */
-public class Xuebi extends ConsumableFood {
-
- public Xuebi() {
- super(BumpItems.XUEBI, RecipeType.MAGIC_WORKBENCH, new ItemStack[]{
- BumpItems.WATER_SUGAR, new ItemStack(Material.WATER_BUCKET), BumpItems.WATER_SUGAR,
- new ItemStack(Material.WATER_BUCKET), BumpItems.WATER_SUGAR, new ItemStack(Material.WATER_BUCKET),
- BumpItems.WATER_SUGAR, new ItemStack(Material.WATER_BUCKET), BumpItems.WATER_SUGAR
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.add(p, 6);
- p.addPotionEffect(new PotionEffect(PotionEffectType.LUCK, 2000, 4));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Zongzi.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Zongzi.java
deleted file mode 100644
index 3b09d835..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/food/Zongzi.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.food;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-
-/**
- * Zongzi. Rice dumpling
- *
- * @author haiman233
- */
-public class Zongzi extends ItemFood {
-
- public Zongzi() {
- super(BumpItems.ZONGZI, RecipeType.MAGIC_WORKBENCH, new ItemStack[]{
- new ItemStack(Material.LILY_PAD), new ItemStack(Material.ACACIA_LEAVES), new ItemStack(Material.LILY_PAD),
- new ItemStack(Material.ACACIA_LEAVES), new ItemStack(Material.WHEAT), new ItemStack(Material.ACACIA_LEAVES),
- new ItemStack(Material.LILY_PAD), new ItemStack(Material.ACACIA_LEAVES), new ItemStack(Material.LILY_PAD)
- });
- }
-
- @Override
- public void applyFoodEffects(Player p) {
- FoodLevelUtils.add(p, 8);
- p.addPotionEffect(new PotionEffect(PotionEffectType.CONDUIT_POWER, 100, 1));
- p.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 1000, 1));
- p.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 100, 1));
- p.addPotionEffect(new PotionEffect(PotionEffectType.FAST_DIGGING, 150, 2));
- p.addPotionEffect(new PotionEffect(PotionEffectType.LUCK, 500, 2));
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/legacy/LegacyAppraisalPaper.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/legacy/LegacyAppraisalPaper.java
deleted file mode 100644
index 33d02ff5..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/legacy/LegacyAppraisalPaper.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.legacy;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.implementation.items.tools.QualityIdentifier;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.LimitedUseItem;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-/**
- * This class is used to upgrade legacy appraisal papers in player's inventory
- * to new ones.
- *
- * @author ybw0014
- * @deprecated This represents legacy quality identifiers, and will be removed soon.
- */
-@Deprecated
-public final class LegacyAppraisalPaper extends LimitedUseItem {
-
- @ParametersAreNonnullByDefault
- public LegacyAppraisalPaper(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.HIDDEN, item, recipeType, recipe);
-
- setMaxUseCount(QualityIdentifier.MAX_USES);
- addItemHandler(getItemHandler());
- }
-
- @Nonnull
- @Override
- public ItemUseHandler getItemHandler() {
- return e -> {
- e.cancel();
-
- Player p = e.getPlayer();
- ItemStack paperItemStack = e.getItem();
-
- if (paperItemStack.getType() == Material.AIR) {
- return;
- }
-
- int usesLeft = getUsesLeft(paperItemStack);
- int amount = paperItemStack.getAmount();
-
- ItemStack newItem = BumpItems.QUALITY_IDENTIFIER.clone();
- newItem.setAmount(amount);
-
- ItemMeta newMeta = newItem.getItemMeta();
- PersistentDataAPI.setInt(newMeta, getStorageKey(), usesLeft);
- newItem.setItemMeta(newMeta);
-
- p.getInventory().setItem(e.getHand(), newItem);
-
- Bump.getLocalization().sendMessage(p, "tool.appraisal_paper.legacy");
- };
- }
-
- private int getUsesLeft(@Nonnull ItemStack itemStack) {
- return PersistentDataAPI.getInt(itemStack.getItemMeta(), getStorageKey(), getMaxUseCount());
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrument.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrument.java
deleted file mode 100644
index 32505958..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrument.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.machines;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Location;
-import org.bukkit.NamespacedKey;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseResult;
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.implementation.items.RandomEquipment;
-import io.github.slimefunguguproject.bump.implementation.items.tools.QualityIdentifier;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.GuiItems;
-import io.github.slimefunguguproject.bump.utils.ValidateUtils;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
-import me.mrCookieSlime.Slimefun.api.BlockStorage;
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
-
-/**
- * This implements the {@link AppraisalInstrument}.
- *
- * It will cost energy and appraise any equipment with appraisable tag.
- *
- * @author ybw0014
- * @see QualityIdentifier
- */
-public final class AppraisalInstrument extends SimpleMenuBlock {
-
- // energy
- public static final int ENERGY_CONSUMPTION = 114514;
-
- private static final int APPRAISE_TYPE_SLOT = 4;
-
- private static final String APPRAISE_TYPE_KEY = "appraise_type";
-
- public AppraisalInstrument() {
- super(BumpItemGroups.MACHINE, BumpItems.APPRAISAL, RecipeType.ENHANCED_CRAFTING_TABLE, new ItemStack[]{
- SlimefunItems.BATTERY, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.BATTERY,
- BumpItems.MECHA_GEAR, BumpItems.CPU, BumpItems.MECHA_GEAR,
- SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.COOLING_UNIT, SlimefunItems.ADVANCED_CIRCUIT_BOARD
- });
- }
-
- @Override
- @Nonnull
- public ItemStack getOperationSlotItem() {
- return GuiItems.APPRAISE_BUTTON;
- }
-
- @Override
- public int getCapacity() {
- return ENERGY_CONSUMPTION;
- }
-
- @ParametersAreNonnullByDefault
- @Override
- protected void onNewInstance(BlockMenu menu, Block b) {
- super.onNewInstance(menu, b);
- updateSelector(menu, b.getLocation());
- }
-
- @ParametersAreNonnullByDefault
- @Override
- protected void onOperate(BlockMenu menu, Block b, Player p, ClickAction action) {
- appraise(menu, p);
- }
-
- @ParametersAreNonnullByDefault
- private void openSelector(Player p, BlockMenu blockMenu, Location l) {
- new AppraisalInstrumentSelector(type -> {
- BlockStorage.addBlockInfo(l, APPRAISE_TYPE_KEY, type.getKey().toString());
- updateSelector(blockMenu, l);
- BumpSound.APPRAISE_TYPE_SELECT.playFor(p);
- blockMenu.open(p);
- }, () -> blockMenu.open(p)).open(p);
- }
-
- @ParametersAreNonnullByDefault
- private void appraise(BlockMenu blockMenu, Player p) {
- ItemStack item = blockMenu.getItemInSlot(getInputSlot());
-
- // null check
- if (!ValidateUtils.noAirItem(item)) {
- Bump.getLocalization().sendMessage(p, "no-input");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- // validate input
- if (!validate(item)) {
- Bump.getLocalization().sendMessage(p, "machine.appraisal.invalid");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- // check if input item is already appraised
- if (AppraiseUtils.isAppraised(item)) {
- Bump.getLocalization().sendMessage(p, "machine.appraisal.appraised");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- // check output slot
- if (blockMenu.getItemInSlot(getOutputSlot()) != null) {
- Bump.getLocalization().sendMessage(p, "output-no-space");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- // check energy
- int charge = getCharge(blockMenu.getLocation());
- if (charge < ENERGY_CONSUMPTION) {
- Bump.getLocalization().sendMessage(p, "not-enough-power");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- // Check current appraise type
- AppraiseType type = getCurrentType(blockMenu.getLocation());
- if (!type.hasPermission(p)) {
- Bump.getLocalization().sendMessage(p, "no-permission");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
- if (!type.isValidItem(item)) {
- Bump.getLocalization().sendMessage(p, "machine.appraisal.not-accepted");
- BumpSound.APPRAISAL_INSTRUMENT_FAIL.playFor(p);
- return;
- }
-
- ItemStack output = item.clone();
- AppraiseResult result = type.appraise();
-
- result.apply(output);
-
- blockMenu.replaceExistingItem(getInputSlot(), null);
- blockMenu.pushItem(output, getOutputSlot());
-
- setCharge(blockMenu.getLocation(), 0);
- Bump.getLocalization().sendMessage(p, "machine.appraisal.success");
- BumpSound.APPRAISAL_INSTRUMENT_SUCCEED.playFor(p);
- }
-
- private boolean validate(@Nonnull ItemStack itemStack) {
- SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
-
- return sfItem instanceof RandomEquipment || AppraiseUtils.isAppraisable(itemStack);
- }
-
- @ParametersAreNonnullByDefault
- private void updateSelector(BlockMenu menu, Location l) {
- AppraiseType type = getCurrentType(l);
- menu.replaceExistingItem(APPRAISE_TYPE_SLOT, GuiItems.appraiseTypeSelector(type));
- menu.addMenuClickHandler(APPRAISE_TYPE_SLOT, (player, slot, itemStack, clickAction) -> {
- openSelector(player, menu, l);
- return false;
- });
- }
-
- @Nonnull
- private AppraiseType getCurrentType(@Nonnull Location loc) {
- String current = BlockStorage.getLocationInfo(loc, APPRAISE_TYPE_KEY);
- AppraiseType type = null;
- if (current != null) {
- NamespacedKey key = NamespacedKey.fromString(current, Bump.getInstance());
- if (key != null) {
- type = AppraiseType.getByKey(key);
- }
- }
-
- if (type == null) {
- type = Bump.getRegistry().getAppraiseTypes().iterator().next();
- }
- return type;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrumentSelector.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrumentSelector.java
deleted file mode 100644
index 2ebe38f3..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AppraisalInstrumentSelector.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.machines;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.bakedlibs.dough.items.CustomItemStack;
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.menus.AppraiseTypesMenu;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-
-import lombok.NonNull;
-
-/**
- * A selector menu that can be opened from {@link AppraisalInstrument}.
- *
- * @author ybw0014
- */
-final class AppraisalInstrumentSelector extends AppraiseTypesMenu {
-
- public AppraisalInstrumentSelector(@NonNull Consumer successCallback, @NonNull Runnable backCallback) {
- super(Bump.getLocalization().getString("gui.appraise_type_selector_menu.title"), successCallback, backCallback);
- }
-
- @Nonnull
- @Override
- public ItemStack getDisplayItem(@Nonnull AppraiseType type) {
- List lore = AppraiseUtils.getDescriptionLore(type);
- lore.addAll(Bump.getLocalization().getStringList("gui.appraise_type_selector_menu.lore"));
-
- return new CustomItemStack(
- Material.PAPER,
- Bump.getLocalization().getString("appraise_info.name", type.getName()),
- lore
- );
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.java
deleted file mode 100644
index b3a86d3c..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.machines;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.collect.Multimap;
-
-import org.bukkit.NamespacedKey;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.attribute.AttributeModifier;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.EquipmentSlot;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.GuiItems;
-import io.github.slimefunguguproject.bump.utils.ValidateUtils;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.slimefunguguproject.bump.utils.tags.BumpTag;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
-
-import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil;
-
-/**
- * The {@link AttributeGrindstone} can purge the appraisal result from
- * appraised equipment.
- *
- * @author ybw0014
- */
-public final class AttributeGrindstone extends SimpleMenuBlock {
-
- // energy
- public static final int ENERGY_CONSUMPTION = 1314;
-
- public AttributeGrindstone() {
- super(BumpItemGroups.MACHINE, BumpItems.ATTRIBUTE_GRINDSTONE, RecipeType.ENHANCED_CRAFTING_TABLE, new ItemStack[]{
- SlimefunItems.ELECTRO_MAGNET, BumpItems.APPRAISAL, SlimefunItems.ELECTRO_MAGNET,
- BumpItems.MECHA_GEAR, BumpItems.CPU, BumpItems.MECHA_GEAR,
- BumpItems.UPDATE_POWER, BumpItems.ZONGZI, BumpItems.UPDATE_POWER
- });
- }
-
- @Override
- @Nonnull
- public ItemStack getOperationSlotItem() {
- return GuiItems.GRIND_BUTTON;
- }
-
- @Override
- public int getCapacity() {
- return ENERGY_CONSUMPTION;
- }
-
- @ParametersAreNonnullByDefault
- @Override
- protected void onOperate(BlockMenu menu, Block b, Player p, ClickAction action) {
- grind(menu, p);
- }
-
- private void grind(@Nonnull BlockMenu blockMenu, @Nonnull Player p) {
- ItemStack item = blockMenu.getItemInSlot(getInputSlot());
-
- // null check
- if (!ValidateUtils.noAirItem(item)) {
- Bump.getLocalization().sendMessage(p, "no-input");
- BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p);
- return;
- }
-
- // check if input item is appraised
- if (!AppraiseUtils.isAppraised(item)) {
- Bump.getLocalization().sendMessage(p, "machine.attribute-grindstone.invalid");
- BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p);
- return;
- }
-
- // check output slot
- if (blockMenu.getItemInSlot(getOutputSlot()) != null) {
- Bump.getLocalization().sendMessage(p, "output-no-space");
- BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p);
- return;
- }
-
- // check energy
- int charge = getCharge(blockMenu.getLocation());
- if (charge < ENERGY_CONSUMPTION) {
- Bump.getLocalization().sendMessage(p, "not-enough-power");
- BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p);
- return;
- }
-
- ItemStack output = item.clone();
- clearAttributes(output);
- blockMenu.replaceExistingItem(getInputSlot(), null);
- blockMenu.pushItem(output, getOutputSlot());
-
- setCharge(blockMenu.getLocation(), 0);
- Bump.getLocalization().sendMessage(p, "machine.attribute-grindstone.success");
- BumpSound.ATTRIBUTE_GRINDSTONE_SUCCEED.playFor(p);
- }
-
- private void clearAttributes(@Nonnull ItemStack itemStack) {
- ItemMeta meta = itemStack.getItemMeta();
- // check the appraising version
- byte version = PersistentDataAPI.getByte(meta, Keys.APPRAISE_VERSION, (byte) 1);
-
- removeModifiers(itemStack, meta, version);
-
- // set pdc
- PersistentDataAPI.setBoolean(meta, Keys.APPRAISABLE, true);
- PersistentDataAPI.remove(meta, Keys.APPRAISE_LEVEL);
-
- // set lore
- String appraisedLore = ChatUtil.color(Bump.getLocalization().getString("lores.appraised"));
- String appraisedLorePrefix = appraisedLore.substring(0, appraisedLore.indexOf("{0}"));
- List lore;
- if (meta.hasLore()) {
- lore = meta.getLore();
- } else {
- lore = new ArrayList<>();
- }
- for (int i = 0; i < lore.size(); i++) {
- if (lore.get(i).startsWith(appraisedLorePrefix)) {
- lore.set(i, ChatUtil.color(Bump.getLocalization().getString("lores.not-appraised")));
- break;
- }
- }
- meta.setLore(lore);
-
- // done
- itemStack.setItemMeta(meta);
- }
-
- @ParametersAreNonnullByDefault
- private void removeModifiers(ItemStack itemStack, ItemMeta meta, byte version) {
- if (version == 1) {
- // legacy version, remove all attribute modifiers
- for (EquipmentSlot slot : EquipmentSlot.values()) {
- if (BumpTag.getTag(slot.name() + "_SLOT").isTagged(itemStack.getType())) {
- meta.removeAttributeModifier(slot);
- }
- }
- } else {
- // new version (for now), remove all bump attribute modifiers
- Multimap modifierMap = meta.getAttributeModifiers();
- if (modifierMap != null) {
- for (Map.Entry entry : modifierMap.entries()) {
- Attribute attribute = entry.getKey();
- AttributeModifier modifier = entry.getValue();
- NamespacedKey key = NamespacedKey.fromString(modifier.getName(), Bump.getInstance());
- if (key != null && AppraiseType.getByKey(key) != null) {
- meta.removeAttributeModifier(attribute, modifier);
- }
- }
- }
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.java
deleted file mode 100644
index e413668b..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.machines;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Location;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
-import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
-import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
-
-import net.guizhanss.guizhanlib.slimefun.machines.MenuBlock;
-
-/**
- * A {@link MenuBlock} that has single input and output slot.
- *
- * Consumes power when use this machine.
- *
- * @author ybw0014
- */
-public abstract class SimpleMenuBlock extends MenuBlock implements EnergyNetComponent {
-
- // gui
- private static final int[] BACKGROUND = {
- 0, 4, 8, 9, 17, 18, 22, 26
- };
- private static final int[] INPUT_BACKGROUND = {
- 1, 2, 3, 10, 12, 19, 20, 21
- };
- private static final int[] OUTPUT_BACKGROUND = {
- 5, 6, 7, 14, 16, 23, 24, 25
- };
- private static final int INPUT_SLOT = 11;
- private static final int OPERATION_SLOT = 13;
- private static final int OUTPUT_SLOT = 15;
-
- /**
- * Constructor.
- *
- * @param itemGroup the {@link ItemGroup} of this {@link MenuBlock}
- * @param item the {@link SlimefunItemStack} of this {@link MenuBlock}
- * @param recipeType the {@link RecipeType} of this {@link MenuBlock}
- * @param recipe the recipe of this {@link MenuBlock}
- */
- @ParametersAreNonnullByDefault
- protected SimpleMenuBlock(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(itemGroup, item, recipeType, recipe);
- }
-
- @Nonnull
- protected abstract ItemStack getOperationSlotItem();
-
- @Override
- protected void setup(BlockMenuPreset blockMenuPreset) {
- blockMenuPreset.drawBackground(ChestMenuUtils.getBackground(), BACKGROUND);
- blockMenuPreset.drawBackground(ChestMenuUtils.getInputSlotTexture(), INPUT_BACKGROUND);
- blockMenuPreset.drawBackground(ChestMenuUtils.getOutputSlotTexture(), OUTPUT_BACKGROUND);
-
- blockMenuPreset.addItem(OPERATION_SLOT, getOperationSlotItem());
- blockMenuPreset.addMenuClickHandler(OPERATION_SLOT, ChestMenuUtils.getEmptyClickHandler());
- }
-
- @Override
- protected void onBreak(@Nonnull BlockBreakEvent e, @Nonnull BlockMenu menu) {
- super.onBreak(e, menu);
- Location location = menu.getLocation();
- menu.dropItems(location, INPUT_SLOT);
- menu.dropItems(location, OUTPUT_SLOT);
- }
-
- @ParametersAreNonnullByDefault
- @Override
- protected void onNewInstance(BlockMenu blockMenu, Block b) {
- super.onNewInstance(blockMenu, b);
- blockMenu.addMenuClickHandler(OPERATION_SLOT, (player, slot, itemStack, clickAction) -> {
- onOperate(blockMenu, b, player, clickAction);
- return false;
- });
- }
-
- @ParametersAreNonnullByDefault
- protected abstract void onOperate(BlockMenu menu, Block b, Player p, ClickAction action);
-
- @Nonnull
- @Override
- public final EnergyNetComponentType getEnergyComponentType() {
- return EnergyNetComponentType.CONSUMER;
- }
-
- protected final int getInputSlot() {
- return INPUT_SLOT;
- }
-
- protected final int getOutputSlot() {
- return OUTPUT_SLOT;
- }
-
- @Override
- protected final int[] getInputSlots() {
- return new int[]{INPUT_SLOT};
- }
-
- @Override
- protected final int[] getOutputSlots() {
- return new int[]{OUTPUT_SLOT};
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/stuff/StuffItem.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/stuff/StuffItem.java
deleted file mode 100644
index ae4c5a7f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/stuff/StuffItem.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.stuff;
-
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock;
-
-/**
- * {@link UnplaceableBlock} items in stuff category.
- *
- * @author ybw0014
- */
-public class StuffItem extends UnplaceableBlock {
- public StuffItem(SlimefunItemStack itemStack, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.STUFF, itemStack, recipeType, recipe);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/GetgoldSpade.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/GetgoldSpade.java
deleted file mode 100644
index baa92cca..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/GetgoldSpade.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.tools;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
-
-import net.guizhanss.guizhanlib.utils.RandomUtil;
-
-/**
- * A {@link GetgoldSpade getting-gold shovel} will give player old coin
- * with chance if player is breaking sand.
- *
- * @author ybw0014
- */
-public class GetgoldSpade extends SimpleSlimefunItem {
-
- public GetgoldSpade() {
- super(BumpItemGroups.TOOL, BumpItems.GETGOLD_SPADE, RecipeType.ENHANCED_CRAFTING_TABLE, new ItemStack[]{
- null, SlimefunItems.GOLD_24K, null,
- null, new ItemStack(Material.STICK), null,
- null, new ItemStack(Material.STICK), null
- });
- }
-
- @Nonnull
- @Override
- public ToolUseHandler getItemHandler() {
- return (e, tool, fortune, drops) -> {
- if (e.getBlock().getType() != Material.SAND) {
- return;
- }
-
- if (!RandomUtil.testChance(1, 4)) {
- return;
- }
-
- if (BumpItems.OLD_COIN.getItem().isDisabledIn(e.getBlock().getWorld())) {
- return;
- }
-
- drops.clear();
- drops.add(BumpItems.OLD_COIN);
-
- Bump.getLocalization().sendActionbarMessage(e.getPlayer(), "tool.getgold_spade");
- };
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.java
deleted file mode 100644
index 2a4cc94c..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.tools;
-
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.GuiItems;
-import io.github.slimefunguguproject.bump.utils.ValidateUtils;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.LimitedUseItem;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack;
-import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
-import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
-
-import net.guizhanss.guizhanlib.minecraft.utils.InventoryUtil;
-
-/**
- * A quality identifier can mark available {@link ItemStack}
- * as appraisable.
- *
- * @author ybw0014
- */
-@SuppressWarnings("deprecation")
-public class QualityIdentifier extends LimitedUseItem {
-
- public static final int MAX_USES = 5;
-
- // gui
- private static final int[] BACKGROUND_SLOT = {
- 0, 8, 9, 17, 18, 22, 26
- };
- private static final int[] INPUT_BORDER = {
- 1, 2, 3, 10, 12, 19, 20, 21
- };
- private static final int[] OUTPUT_BORDER = {
- 5, 6, 7, 14, 16, 23, 24, 25
- };
- private static final int INFO_SLOT = 4;
- private static final int INPUT_SLOT = 11;
- private static final int APPRAISE_BUTTON = 13;
- private static final int OUTPUT_SLOT = 15;
-
- @ParametersAreNonnullByDefault
- public QualityIdentifier(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.TOOL, item, recipeType, recipe);
-
- setMaxUseCount(MAX_USES);
- addItemHandler(getItemHandler());
- }
-
- @Nonnull
- @Override
- public ItemUseHandler getItemHandler() {
- return e -> {
- e.cancel();
-
- Player p = e.getPlayer();
- ItemStack paperItemStack = e.getItem();
-
- if (paperItemStack.getType() == Material.AIR) {
- return;
- }
-
- if (paperItemStack.getAmount() > 1) {
- Bump.getLocalization().sendMessage(p, "stacked");
- return;
- }
-
- // Open menu
- ChestMenu menu = new ChestMenu(paperItemStack.getItemMeta().getDisplayName());
- createMenu(p, menu, paperItemStack);
- menu.open(p);
- };
- }
-
- @ParametersAreNonnullByDefault
- private void createMenu(Player p, ChestMenu menu, ItemStack paperItemStack) {
- menu.setPlayerInventoryClickable(true);
-
- // Open sound
- menu.addMenuOpeningHandler(player -> {
- BumpSound.QUALITY_IDENTIFIER_OPEN.playFor(p);
- });
-
- // Setup menu
- for (int i : BACKGROUND_SLOT) {
- menu.addItem(i, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
- }
- for (int i : INPUT_BORDER) {
- menu.addItem(i, ChestMenuUtils.getInputSlotTexture(), ChestMenuUtils.getEmptyClickHandler());
- }
- for (int i : OUTPUT_BORDER) {
- menu.addItem(i, ChestMenuUtils.getOutputSlotTexture(), ChestMenuUtils.getEmptyClickHandler());
- }
-
- // Add status
- menu.addItem(INFO_SLOT, getUsesLeftItem(getUsesLeft(paperItemStack)), ChestMenuUtils.getEmptyClickHandler());
-
- // Add menu close handler
- menu.addMenuCloseHandler(player -> {
- InventoryUtil.push(p, menu.getItemInSlot(INPUT_SLOT));
- InventoryUtil.push(p, menu.getItemInSlot(OUTPUT_SLOT));
- });
-
- // Block Quality identifier click
- menu.addPlayerInventoryClickHandler((player, slot, item, action) -> {
- SlimefunItem sfItem = SlimefunItem.getByItem(item);
- return !(sfItem instanceof QualityIdentifier);
- });
-
- // Add appraise button handler
- menu.addItem(APPRAISE_BUTTON, GuiItems.APPRAISE_PAPER, getAppraiseButtonHandler(p, menu, paperItemStack));
- }
-
- @Nonnull
- @ParametersAreNonnullByDefault
- private ChestMenu.MenuClickHandler getAppraiseButtonHandler(Player p, ChestMenu menu, ItemStack paperItemStack) {
- return (player, slot, item, action) -> {
- // Check input slot
- ItemStack input = menu.getItemInSlot(INPUT_SLOT);
-
- if (!ValidateUtils.noAirItem(input)) {
- Bump.getLocalization().sendMessage(p, "no-input");
- BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(player);
- return false;
- }
-
- // Check output slot
- if (menu.getItemInSlot(OUTPUT_SLOT) != null) {
- Bump.getLocalization().sendMessage(p, "output-no-space");
- BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(player);
- return false;
- }
-
- // validate item
- if (isValidItem(input)) {
- // item can be marked appraisable
- ItemStack output = input.clone();
- AppraiseUtils.setAppraisable(output);
- menu.replaceExistingItem(INPUT_SLOT, null);
- menu.replaceExistingItem(OUTPUT_SLOT, output);
-
- damageItem(p, paperItemStack);
-
- /*
- * The paper is used up, should close the gui.
- * Otherwise, update the status slot.
- */
- if (paperItemStack.getType() == Material.AIR) {
- p.closeInventory();
- } else {
- menu.replaceExistingItem(INFO_SLOT, getUsesLeftItem(getUsesLeft(paperItemStack)));
-
- // play sound only if appraisal paper is not broken
- BumpSound.QUALITY_IDENTIFIER_SUCCEED.playFor(player);
- }
-
- Bump.getLocalization().sendMessage(p, "tool.appraisal_paper.success");
- } else {
- Bump.getLocalization().sendMessage(p, "tool.appraisal_paper.invalid");
- BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(player);
- }
-
- return false;
- };
- }
-
- /**
- * Validate the item. The item that can be marked appraisable
- * should meet these requirements:
- * - has not been appraised yet
- * - has not been marked appraisable yet
- *
- * @param itemStack The {@link ItemStack} to be validated.
- *
- * @return If the {@link ItemStack} is applicable to appraisal paper.
- */
- private boolean isValidItem(@Nonnull ItemStack itemStack) {
- final Set types = Bump.getRegistry().getAppraiseTypes();
- // find any match type
- for (AppraiseType type : types) {
- if (type.isValidItem(itemStack)
- && !AppraiseUtils.isAppraised(itemStack)
- && !AppraiseUtils.isAppraisable(itemStack)
- ) {
- return true;
- }
- }
- return false;
- }
-
- private int getUsesLeft(@Nonnull ItemStack itemStack) {
- return PersistentDataAPI.getInt(itemStack.getItemMeta(), getStorageKey(), getMaxUseCount());
- }
-
- @Nonnull
- private ItemStack getUsesLeftItem(int usesLeft) {
- return new CustomItemStack(
- Material.LIME_STAINED_GLASS_PANE,
- LoreBuilder.usesLeft(usesLeft)
- );
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.java
deleted file mode 100644
index 57c1bd6a..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.attributes.CostHungerItem;
-import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
-import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
-
-/**
- * A {@link BumpBow} is a {@link SlimefunItem} which has an {@link ItemSetting} of damageable
- *
- * @author ybw0014
- */
-public abstract class BumpBow extends SimpleSlimefunItem implements DamageableItem, CostHungerItem {
-
- protected final IntRangeSetting hungerCost;
- private final ItemSetting costDurability = new ItemSetting<>(this, "cost-durability", true);
-
- @ParametersAreNonnullByDefault
- protected BumpBow(int hunger, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.WEAPON, item, recipeType, recipe);
-
- // durability cost
- addItemSetting(costDurability);
-
- // hunger cost
- Preconditions.checkArgument(hunger >= 0 && hunger <= 20, "Hunger cost must be between 0 and 20");
- hungerCost = new IntRangeSetting(this, "hunger-cost", 0, hunger, 20);
- addItemSetting(hungerCost);
- }
-
- @Override
- public boolean isDamageable() {
- return costDurability.getValue();
- }
-
- @Nonnull
- public ItemSetting getHungerCostSetting() {
- return hungerCost;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.java
deleted file mode 100644
index 2e3b7d8f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.attributes.CooldownItem;
-import io.github.slimefunguguproject.bump.core.attributes.CostHungerItem;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
-
-/**
- * A {@link BumpSword} is a {@link SlimefunItem} with an {@link ItemSetting} of hunger cost and cooldown
- *
- * @author ybw0014
- */
-public abstract class BumpSword extends SimpleSlimefunItem implements CostHungerItem, CooldownItem {
-
- protected final IntRangeSetting hungerCost;
- protected final IntRangeSetting cooldownInSeconds = new IntRangeSetting(this, "cooldown-in-seconds", 0, 0, Integer.MAX_VALUE);
-
- @ParametersAreNonnullByDefault
- protected BumpSword(int hunger, SlimefunItemStack itemStack, RecipeType recipeType, ItemStack[] recipe) {
- super(BumpItemGroups.WEAPON, itemStack, recipeType, recipe);
-
- // hunger cost
- Preconditions.checkArgument(hunger >= 0 && hunger <= 20, "The default hunger cost must be between 0 and 20");
- hungerCost = new IntRangeSetting(this, "hunger-cost", 0, hunger, 20);
- addItemSetting(hungerCost);
-
- // cooldown
- addItemSetting(cooldownInSeconds);
- }
-
- @Nonnull
- public ItemSetting getHungerCostSetting() {
- return hungerCost;
- }
-
- public int getCooldown() {
- return cooldownInSeconds.getValue();
- }
-
- /**
- * This function is called when player use this sword
- *
- * @param p the {@link Player} that uses this sword
- * @param sword the {@link ItemStack} of this sword
- */
- public abstract void onItemUse(Player p, ItemStack sword);
-
- @Nonnull
- @Override
- public ItemUseHandler getItemHandler() {
- return e -> {
- Player p = e.getPlayer();
- ItemStack item = e.getItem();
-
- if (isCooldown(item)) {
- if (costHunger(p)) {
- setCooldown(item);
- onItemUse(p, item);
- } else {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.low-food-level");
- }
- } else {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.cooldown");
- }
- };
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/DevilSword.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/DevilSword.java
deleted file mode 100644
index f9cbe07f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/DevilSword.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import org.bukkit.Particle;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Projectile;
-import org.bukkit.entity.SmallFireball;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * {@link DevilSword Demon Slayer Sword} will launch {@link SmallFireball} when using.
- *
- * @author ybw0014
- */
-public class DevilSword extends BumpSword {
-
- public DevilSword() {
- super(5, BumpItems.DEVIL_SWORD, RecipeType.ARMOR_FORGE, new ItemStack[]{
- SlimefunItems.MAGIC_LUMP_2, SlimefunItems.ENDER_RUNE, SlimefunItems.MAGIC_LUMP_2,
- SlimefunItems.FIRE_RUNE, SlimefunItems.FIRE_RUNE, SlimefunItems.MAGIC_LUMP_2,
- SlimefunItems.ENDER_RUNE, SlimefunItems.MAGIC_LUMP_2, null
- });
- }
-
- @Override
- public void onItemUse(Player p, ItemStack itemStack) {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.devil_sword");
-
- BumpSound.DEVIL_SWORD_USE.playFor(p);
-
- for (int i = 0; i < 20; i++) {
- Projectile projectile = p.launchProjectile(SmallFireball.class);
- WeaponProjectileTask.track(projectile);
- p.spawnParticle(Particle.ENCHANTMENT_TABLE, p.getLocation(), 1);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/LightBow.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/LightBow.java
deleted file mode 100644
index 8d0546d6..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/LightBow.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * {@link LightBow God's Punishment Bow} will strike lightning at player's pointed block.
- *
- * @author ybw0014
- */
-public class LightBow extends BumpBow {
-
- public LightBow() {
- super(10, BumpItems.LIGHT_BOW, RecipeType.ARMOR_FORGE, new ItemStack[]{
- SlimefunItems.LIGHTNING_RUNE, SlimefunItems.STAFF_STORM, SlimefunItems.LIGHTNING_RUNE,
- SlimefunItems.POWER_CRYSTAL, SlimefunItems.STAFF_STORM, SlimefunItems.LIGHTNING_RUNE,
- SlimefunItems.STAFF_STORM
- });
- }
-
- @Nonnull
- @Override
- public BowUseHandler getItemHandler() {
- return (e, p, item) -> {
- e.setCancelled(true);
-
- Block target = p.getTargetBlock(null, 200);
- if (target.getType() == Material.AIR) {
- return;
- }
-
- Location targetLocation = target.getLocation();
-
- if (costHunger(p)) {
- damageItem(p, item);
-
- Bump.getLocalization().sendActionbarMessage(p, "weapon.light_bow");
-
- for (int i = 0; i < 10; i++) {
- p.getWorld().strikeLightning(targetLocation);
- }
- } else {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.low-food-level");
- }
- };
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkyDevilSword.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkyDevilSword.java
deleted file mode 100644
index 33565296..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkyDevilSword.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import org.bukkit.Sound;
-import org.bukkit.entity.DragonFireball;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Projectile;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-import org.bukkit.scheduler.BukkitRunnable;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-
-/**
- * {@link SkyDevilSword Heaven-demon Crumble Sword} will fire 3 {@link DragonFireball dragon fireballs}
- * and get some potion effects when using
- *
- * @author ybw0014
- */
-public class SkyDevilSword extends BumpSword {
-
- public SkyDevilSword() {
- super(5, BumpItems.SKY_DEVIL_SWORD, RecipeType.ENHANCED_CRAFTING_TABLE, new ItemStack[]{
- null, null, null,
- BumpItems.SKY_SWORD, BumpItems.UPDATE_POWER, BumpItems.DEVIL_SWORD,
- null, null, null
- });
- }
-
- @Override
- public void onItemUse(Player p, ItemStack itemStack) {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.sky_devil_sword.activated");
-
- p.setGlowing(true);
- p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 300, 3));
- p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 300, 3));
-
- new BukkitRunnable() {
- int count = 3;
-
- @Override
- public void run() {
- if (count > 0) {
- p.playSound(p.getLocation(), Sound.ENTITY_ENDER_DRAGON_SHOOT, 1.0F, 1.0F);
- Projectile projectile = p.launchProjectile(DragonFireball.class);
- WeaponProjectileTask.track(projectile);
- count--;
- } else {
- cancel();
- p.setGlowing(false);
- Bump.getLocalization().sendActionbarMessage(p, "weapon.sky_devil_sword.deactivated");
- }
- }
- }.runTaskTimer(Bump.getInstance(), 1L, 100L);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkySword.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkySword.java
deleted file mode 100644
index 99810267..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SkySword.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Particle;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.util.Vector;
-
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-/**
- * {@link SkySword Heaven Breaking Sword} will lift player up to the sky when using.
- *
- * @author ybw0014
- */
-public class SkySword extends BumpSword {
-
- public SkySword() {
- super(5, BumpItems.SKY_SWORD, RecipeType.ARMOR_FORGE, new ItemStack[]{
- SlimefunItems.MAGIC_LUMP_2, SlimefunItems.AIR_RUNE, SlimefunItems.MAGIC_LUMP_2,
- SlimefunItems.RAINBOW_RUNE, SlimefunItems.RAINBOW_RUNE, SlimefunItems.MAGIC_LUMP_2,
- SlimefunItems.AIR_RUNE, SlimefunItems.MAGIC_LUMP_2, null
- });
- }
-
- @Override
- @ParametersAreNonnullByDefault
- public void onItemUse(Player p, ItemStack itemStack) {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.sky_sword.activated");
-
- // directly up
- Vector vector = new Vector(0, 3, 0);
- p.setVelocity(vector);
-
- BumpSound.SKY_SWORD_USE.playFor(p);
- for (int i = 0; i < 20; i++) {
- p.spawnParticle(Particle.EXPLOSION_HUGE, p.getLocation(), 1);
- }
- PersistentDataAPI.setBoolean(p, Keys.SKY_SWORD_PROTECTED, true);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.java
deleted file mode 100644
index 60dff14a..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.utils.FoodLevelUtils;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
-import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
-
-/**
- * {@link SoulSword Soul sword} will convert hunger to health.
- *
- * @author ybw0014
- */
-public class SoulSword extends SimpleSlimefunItem {
-
- public SoulSword() {
- super(BumpItemGroups.WEAPON, BumpItems.SOUL_SWORD, RecipeType.ARMOR_FORGE, new ItemStack[]{
- null, null, null,
- BumpItems.SOUL_PAPER, new ItemStack(Material.DIAMOND_SWORD), BumpItems.SOUL_PAPER,
- null, null, null
- });
- }
-
- @Nonnull
- @Override
- public ItemUseHandler getItemHandler() {
- return e -> {
- Player p = e.getPlayer();
- double health = p.getHealth();
- double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
- int foodLevel = p.getFoodLevel();
-
- if (maxHealth <= health) {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.unavailable");
- return;
- }
-
- if (foodLevel >= 2) {
- if (maxHealth - health <= foodLevel) {
- // Food level can be partially converted to full health
- FoodLevelUtils.set(p, (int) (foodLevel - (maxHealth - health)));
- p.setHealth(maxHealth);
- Bump.getLocalization().sendActionbarMessage(p, "weapon.soul_sword.converted-part");
- } else {
- // Food level can be all converted to health
- FoodLevelUtils.set(p, 0);
- p.setHealth(health + foodLevel);
- Bump.getLocalization().sendActionbarMessage(p, "weapon.soul_sword.converted-all");
- }
-
- BumpSound.SOUL_SWORD_USE.playFor(p);
- } else {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.low-food-level");
- }
- };
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.java
deleted file mode 100644
index 0cd899f5..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.items.weapons;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Sound;
-import org.bukkit.entity.Projectile;
-import org.bukkit.entity.WitherSkull;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-
-/**
- * {@link WitherSkullBow Withered bow} will launch {@link WitherSkull} when using.
- *
- * @author ybw0014
- */
-public class WitherSkullBow extends BumpBow {
-
- public WitherSkullBow() {
- super(5, BumpItems.WITHERSKULL_BOW, RecipeType.ARMOR_FORGE, new ItemStack[]{
- SlimefunItems.NECROTIC_SKULL, BumpItems.PEACH_WOOD, SlimefunItems.NECROTIC_SKULL,
- SlimefunItems.POWER_CRYSTAL, BumpItems.PEACH_WOOD, SlimefunItems.NECROTIC_SKULL,
- BumpItems.PEACH_WOOD, null, null
- });
- }
-
- @Nonnull
- @Override
- public BowUseHandler getItemHandler() {
- return (e, p, item) -> {
- e.setCancelled(true);
- if (costHunger(p)) {
- damageItem(p, item);
-
- Bump.getLocalization().sendActionbarMessage(p, "weapon.wither_skull_bow");
-
- p.playSound(p.getLocation(), Sound.ENTITY_WITHER_SHOOT, 1.0F, 1.0F);
-
- Projectile projectile = p.launchProjectile(WitherSkull.class);
- WeaponProjectileTask.track(projectile);
- } else {
- Bump.getLocalization().sendActionbarMessage(p, "weapon.low-food-level");
- }
- };
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.java
deleted file mode 100644
index b46d820d..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.listeners;
-
-import org.bukkit.entity.Arrow;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityShootBowEvent;
-
-import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-
-/**
- * This {@link Listener} will call {@link BowUseHandler}
- * when {@link Player} fires with a bow.
- *
- * @author ybw0014
- * @see BowUseHandler
- */
-public final class BowShootListener implements Listener {
- @EventHandler
- public void onBowUse(EntityShootBowEvent e) {
- if (e.getEntity() instanceof Player player && e.getProjectile() instanceof Arrow) {
- SlimefunItem bow = SlimefunItem.getByItem(e.getBow());
-
- if (bow != null) {
- bow.callItemHandler(BowUseHandler.class, handler -> handler.onUse(e, player, e.getBow()));
- }
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.java
deleted file mode 100644
index 185de912..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.listeners;
-
-import org.bukkit.Particle;
-import org.bukkit.entity.AreaEffectCloud;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-
-/**
- * This {@link Listener} is responsible for dragon breath damage.
- *
- * @author ybw0014
- */
-public class DragonBreathListener implements Listener {
- @EventHandler
- public void onPlayerDamaged(EntityDamageByEntityEvent e) {
- if (e.getDamager() instanceof AreaEffectCloud damager
- && damager.getParticle() == Particle.DRAGON_BREATH
- && damager.getSource() instanceof Player damageSource
- && e.getEntity() instanceof Player p
- && damageSource.getUniqueId().equals(p.getUniqueId())
- ) {
- e.setCancelled(true);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/SkySwordListener.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/SkySwordListener.java
deleted file mode 100644
index fdbdc4ac..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/listeners/SkySwordListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.listeners;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageEvent;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.SkySword;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-/**
- * This {@link Listener} is related to {@link SkySword}.
- *
- * @author ybw0014
- * @see SkySword
- */
-public final class SkySwordListener implements Listener {
- @EventHandler
- public void onPlayerHitGround(@Nonnull EntityDamageEvent e) {
- if (e.getEntity() instanceof Player p
- && e.getCause() == EntityDamageEvent.DamageCause.FALL
- && PersistentDataAPI.getBoolean(p, Keys.SKY_SWORD_PROTECTED)
- ) {
- e.setCancelled(true);
- Bump.getLocalization().sendActionbarMessage(p, "weapon.sky_sword.protected");
- PersistentDataAPI.setBoolean(p, Keys.SKY_SWORD_PROTECTED, false);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypeMenu.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypeMenu.java
deleted file mode 100644
index 586134d5..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypeMenu.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.menus;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.Sound;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.EquipmentSlot;
-import org.bukkit.inventory.ItemFlag;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.bakedlibs.dough.items.CustomItemStack;
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseAttribute;
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.AppraiseUtils;
-import io.github.slimefunguguproject.bump.utils.Utils;
-import io.github.slimefunguguproject.bump.utils.constant.Strings;
-import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
-import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
-
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-
-/**
- * This menu displays the details of an {@link AppraiseType}.
- *
- * @author ybw0014
- */
-@RequiredArgsConstructor
-public final class AppraiseTypeMenu {
- private static final int GUIDE_BACK = 0;
-
- private static final int INFO_SLOT = 4;
-
- private static final int EQUIPMENT_TYPE_SLOT = 12;
- private static final int MATERIAL_SLOT = 13;
- private static final int EQUIPMENT_SLOT_SLOT = 14;
-
- private static final int ATTRIBUTES_START = 27;
-
- @NonNull
- public final AppraiseType appraiseType;
- @NonNull
- public final Runnable backCallback;
-
- /**
- * Open the menu to {@link Player}.
- *
- * @param p The {@link Player} to open the menu to.
- */
- public void open(@Nonnull Player p) {
- final ChestMenu chestMenu = new ChestMenu(appraiseType.getName());
- chestMenu.setEmptySlotsClickable(false);
- setupMenu(p, chestMenu);
- chestMenu.open(p);
- }
-
- @ParametersAreNonnullByDefault
- private void setupMenu(Player player, ChestMenu menu) {
- // Sound
- menu.addMenuOpeningHandler(p -> p.playSound(p.getLocation(), Sound.ITEM_BOOK_PAGE_TURN, 1.0F, 1.0F));
-
- // Back
- menu.addItem(GUIDE_BACK, ChestMenuUtils.getBackButton(
- player,
- "",
- ChatColor.GRAY + Slimefun.getLocalization().getMessage(player, "guide.back.guide")
- ));
- menu.addMenuClickHandler(GUIDE_BACK, (p, slot, itemStack, clickAction) -> {
- backCallback.run();
- return false;
- });
-
- menu.addItem(INFO_SLOT, getAppraiseInfoItem(appraiseType));
- menu.addMenuClickHandler(INFO_SLOT, ChestMenuUtils.getEmptyClickHandler());
-
- menu.addItem(EQUIPMENT_TYPE_SLOT, getEquipmentTypeItem(appraiseType));
- menu.addMenuClickHandler(EQUIPMENT_TYPE_SLOT, ChestMenuUtils.getEmptyClickHandler());
-
- menu.addItem(MATERIAL_SLOT, getMaterialItem(appraiseType));
- menu.addMenuClickHandler(MATERIAL_SLOT, ChestMenuUtils.getEmptyClickHandler());
-
- menu.addItem(EQUIPMENT_SLOT_SLOT, getEquipmentSlotItem(appraiseType));
- menu.addMenuClickHandler(EQUIPMENT_SLOT_SLOT, ChestMenuUtils.getEmptyClickHandler());
-
- int slot = ATTRIBUTES_START;
- for (AppraiseAttribute attribute : appraiseType.getAttributes()) {
- menu.addItem(slot, getAppraiseAttributeItem(attribute));
- menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler());
-
- slot++;
- if (slot > 53) {
- break;
- }
- }
- }
-
- @Nonnull
- private ItemStack getAppraiseInfoItem(@Nonnull AppraiseType type) {
- return new CustomItemStack(
- Material.ANVIL,
- Bump.getLocalization().getString("appraise_info.name", type.getName()),
- AppraiseUtils.getDescriptionLore(type)
- );
- }
-
- @Nonnull
- private ItemStack getEquipmentTypeItem(@Nonnull AppraiseType type) {
- String equipmentType = type.getEquipmentType().toString();
- return new CustomItemStack(
- Material.DIAMOND_SWORD,
- Bump.getLocalization().getString("appraise_info.equipment_type.name", equipmentType),
- Bump.getLocalization().getString("appraise_info.equipment_type." + equipmentType.toLowerCase(Locale.ROOT))
- );
- }
-
- @Nonnull
- private ItemStack getMaterialItem(@Nonnull AppraiseType type) {
- CustomItemStack result;
- if (type.checkMaterial()) {
- // Enabled checking material, display materials as well (cap at 10)
- List lore = Bump.getLocalization().getStringList("appraise_info.material.lore_enabled");
- lore.add("");
-
- final List materials = new ArrayList<>(type.getValidMaterials());
- int size = Math.min(materials.size(), 10);
- final List subList = materials.subList(0, size);
-
- for (Material material : subList) {
- lore.add(ChatColor.GRAY + Utils.getMaterialName(material));
- }
-
- if (materials.size() > 10) {
- lore.add(Bump.getLocalization().getString("appraise_info.material.lore_enabled_more", materials.size() - size));
- }
-
- result = new CustomItemStack(
- Material.FILLED_MAP,
- Bump.getLocalization().getString("appraise_info.material.name", Strings.CHECK),
- lore
- );
- } else {
- result = new CustomItemStack(
- Material.MAP,
- Bump.getLocalization().getString("appraise_info.material.name", Strings.CROSS),
- Bump.getLocalization().getStringList("appraise_info.material.lore_disabled")
- );
- }
- return result.addFlags(ItemFlag.HIDE_POTION_EFFECTS);
- }
-
- @Nonnull
- private ItemStack getEquipmentSlotItem(@Nonnull AppraiseType type) {
- List lore = Bump.getLocalization().getStringList("appraise_info.equipment_slot.lore");
- lore.add("");
-
- for (EquipmentSlot slot : type.getValidEquipmentSlots()) {
- lore.add(ChatColor.GRAY + slot.toString());
- }
-
- return new CustomItemStack(
- Material.IRON_CHESTPLATE,
- Bump.getLocalization().getString("appraise_info.equipment_slot.name"),
- lore
- );
- }
-
- @Nonnull
- private ItemStack getAppraiseAttributeItem(@Nonnull AppraiseAttribute attribute) {
- return new CustomItemStack(
- Material.PAPER,
- Bump.getLocalization().getString("appraise_info.attribute.name", attribute.getAttribute().toString()),
- Bump.getLocalization().getString("appraise_info.attribute.range", attribute.getMin(), attribute.getMax()),
- Bump.getLocalization().getString("appraise_info.attribute.weight", attribute.getWeight())
- );
- }
-
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypesMenu.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypesMenu.java
deleted file mode 100644
index 405db33f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/menus/AppraiseTypesMenu.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.menus;
-
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.ChatColor;
-import org.bukkit.Sound;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
-import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
-
-import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
-
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-
-/**
- * This class will open a menu with all {@link AppraiseType}.
- *
- * @author ybw0014
- */
-@SuppressWarnings("ConstantConditions")
-@RequiredArgsConstructor
-public abstract class AppraiseTypesMenu {
- private static final int PAGE_SIZE = 36;
-
- private static final int GUIDE_BACK = 1;
-
- private static final int PAGE_PREVIOUS = 46;
- private static final int PAGE_NEXT = 52;
-
- private static final int[] HEADER = new int[]{
- 0, 1, 2, 3, 4, 5, 6, 7, 8
- };
- private static final int[] FOOTER = new int[]{
- 45, 46, 47, 48, 49, 50, 51, 52, 53
- };
-
- /**
- * The display name of menu.
- */
- @NonNull
- private final String name;
-
- /**
- * The callback is called after selecting an {@link AppraiseType}.
- */
- @NonNull
- private final Consumer successCallback;
-
- /**
- * The callback is called after clicking on back button.
- */
- @NonNull
- private final Runnable backCallback;
-
- /**
- * Open the menu to {@link Player}.
- *
- * @param p The {@link Player} to open the menu to.
- */
- public void open(@Nonnull Player p) {
- Preconditions.checkArgument(p != null, "Player cannot be null");
-
- final ChestMenu chestMenu = new ChestMenu(name);
-
- for (int slot : HEADER) {
- chestMenu.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
- }
- for (int slot : FOOTER) {
- chestMenu.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
- }
-
- chestMenu.setEmptySlotsClickable(false);
- displayCollection(p, chestMenu, 1);
- chestMenu.open(p);
- }
-
- @ParametersAreNonnullByDefault
- private void displayCollection(Player player, ChestMenu menu, int page) {
- final List appraiseTypes = Bump.getRegistry().getAppraiseTypes()
- .stream()
- .filter(type -> type.hasPermission(player))
- .collect(Collectors.toList());
- final int total = appraiseTypes.size();
- final int totalPages = (int) Math.ceil(total / (double) PAGE_SIZE);
- final int start = (page - 1) * PAGE_SIZE;
- final int end = Math.min(start + PAGE_SIZE, total);
-
- final List subList = appraiseTypes.subList(start, end);
-
- setupFooter(player, menu, page, totalPages);
-
- // Sound
- player.playSound(player.getLocation(), Sound.ITEM_BOOK_PAGE_TURN, 1.0F, 1.0F);
-
- // Back
- menu.replaceExistingItem(GUIDE_BACK, ChestMenuUtils.getBackButton(
- player,
- "",
- ChatColor.GRAY + Slimefun.getLocalization().getMessage(player, "guide.back.guide")
- ));
- menu.addMenuClickHandler(GUIDE_BACK, (p, slot, itemStack, clickAction) -> {
- backCallback.run();
- return false;
- });
-
- for (int i = 0; i < PAGE_SIZE; i++) {
- final int slot = i + 9;
-
- if (i + 1 <= subList.size()) {
- final AppraiseType appraiseType = subList.get(i);
- menu.replaceExistingItem(slot, getDisplayItem(appraiseType));
- menu.addMenuClickHandler(slot, (p, slot1, itemStack, clickAction) -> {
- successCallback.accept(appraiseType);
- return false;
- });
- } else {
- menu.replaceExistingItem(slot, null);
- menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler());
- }
- }
- }
-
- @Nonnull
- public abstract ItemStack getDisplayItem(@Nonnull AppraiseType type);
-
- @ParametersAreNonnullByDefault
- private void setupFooter(Player player, ChestMenu menu, int page, int totalPages) {
- for (int slot : FOOTER) {
- menu.replaceExistingItem(slot, ChestMenuUtils.getBackground());
- menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler());
- }
-
- menu.replaceExistingItem(PAGE_PREVIOUS, ChestMenuUtils.getPreviousButton(player, page, totalPages));
- menu.addMenuClickHandler(PAGE_PREVIOUS, (p, slot, itemStack, clickAction) -> {
- final int previousPage = page - 1;
- if (previousPage >= 1) {
- displayCollection(p, menu, previousPage);
- }
- return false;
- });
-
- menu.replaceExistingItem(PAGE_NEXT, ChestMenuUtils.getNextButton(player, page, totalPages));
- menu.addMenuClickHandler(PAGE_NEXT, (p, slot, itemStack, clickAction) -> {
- final int nextPage = page + 1;
- if (nextPage <= totalPages) {
- displayCollection(p, menu, nextPage);
- }
- return false;
- });
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.java
deleted file mode 100644
index 7cd73208..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.setup;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.inventory.EquipmentSlot;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.api.exceptions.AppraiseTypeKeyConflictException;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.ConfigUtils;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class set up the default appraisal types.
- *
- * The logs in this class should be localizable.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class AppraiseSetup {
- public static void setupTypes() {
- AddonConfig config = new AddonConfig("appraise-types.yml");
- config.save();
- config.reload();
-
- Bump.getLocalization().log(Level.INFO, "loading-appraise-types");
- Set types = config.getKeys(false);
- for (String type : types) {
- Bump.getLocalization().log(Level.INFO, "loading-appraise-type", type);
- if (!config.getBoolean(type + ".enabled")) {
- Bump.getLocalization().log(Level.INFO, "disabled-appraise-type", type);
- continue;
- }
-
- try {
- // raw values
- String name = config.getString(type + ".name");
- List description = config.getStringList(type + ".description");
- String permission = config.getString(type + ".permission");
- String equipmentTypeStr = config.getString(type + ".equipment-type");
- boolean checkMaterial = config.getBoolean(type + ".check-material");
- List validMaterials = config.getStringList(type + ".materials");
- List validSlimefunItemIds = config.getStringList(type + ".slimefun-items");
- List validEquipmentSlots = config.getStringList(type + ".equipment-slots");
- ConfigurationSection attributesSection = config.getConfigurationSection(type + ".attributes");
- Set attributes = attributesSection.getKeys(false);
-
- // parsed values
- AppraiseType.EquipmentType equipmentType = AppraiseType.EquipmentType.valueOf(equipmentTypeStr);
- Set equipmentSlots = ConfigUtils.parseEquipmentSlots(validEquipmentSlots);
- Set materials = ConfigUtils.parseMaterials(validMaterials);
-
- AppraiseType appraiseType = new AppraiseType(Bump.createKey(type))
- .setName(name)
- .setPermission(permission)
- .setDescription(description)
- .setEquipmentType(equipmentType)
- .addValidEquipmentSlots(equipmentSlots)
- .checkMaterial(checkMaterial)
- .addValidMaterials(materials)
- .addValidSlimefunItemIds(validSlimefunItemIds);
-
- for (String attr : attributes) {
- Attribute attribute = Attribute.valueOf(attr);
- double min = attributesSection.getDouble(attr + ".min");
- double max = attributesSection.getDouble(attr + ".max");
- String weightStr = attributesSection.getString(attr + ".weight");
- double weight = -1;
- if (weightStr != null) {
- try {
- weight = Double.parseDouble(weightStr);
- } catch (NumberFormatException ignored) {
- }
- }
- appraiseType.addAttribute(attribute, min, max, weight);
- }
-
- appraiseType.register(Bump.getInstance());
- Bump.getLocalization().log(Level.INFO, "loaded-appraise-type", type);
- } catch (NullPointerException | IllegalArgumentException | AppraiseTypeKeyConflictException |
- InvalidConfigurationException ex) {
- Bump.getLocalization().log(Level.SEVERE, "error-loading-appraise-type", type, ex.getMessage());
- }
- }
- }
-
- public static void setupStars() {
- final AddonConfig config = Bump.getRegistry().getConfig();
- final Map starThreshold = Bump.getRegistry().getStarThresholds();
- ConfigurationSection section = config.getConfigurationSection("appraise.stars");
- if (section == null) {
- Bump.getLocalization().log(Level.INFO, "missing-appraise-stars");
- Bump.getLocalization().log(Level.INFO, "use-default-appraise-stars");
- setDefaultStarThreshold(starThreshold);
- return;
- }
- Set keys = section.getKeys(false);
- try {
- for (String keyStr : keys) {
- byte key = Byte.parseByte(keyStr);
- if (key < 0 || key > 100) {
- throw new IllegalArgumentException();
- }
- int intValue = section.getInt(keyStr);
- if (intValue < 0 || intValue > 127) {
- throw new IllegalArgumentException();
- }
- byte value = (byte) intValue;
- starThreshold.put(key, value);
- }
- } catch (IllegalArgumentException ex) {
- Bump.getLocalization().log(Level.INFO, "invalid-appraise-stars");
- Bump.getLocalization().log(Level.INFO, "use-default-appraise-stars");
- setDefaultStarThreshold(starThreshold);
- }
- }
-
- private void setDefaultStarThreshold(@Nonnull Map starThreshold) {
- starThreshold.clear();
- starThreshold.put((byte) 100, (byte) 20);
- starThreshold.put((byte) 98, (byte) 10);
- starThreshold.put((byte) 96, (byte) 9);
- starThreshold.put((byte) 92, (byte) 8);
- starThreshold.put((byte) 88, (byte) 7);
- starThreshold.put((byte) 82, (byte) 6);
- starThreshold.put((byte) 74, (byte) 5);
- starThreshold.put((byte) 64, (byte) 4);
- starThreshold.put((byte) 48, (byte) 3);
- starThreshold.put((byte) 30, (byte) 2);
- starThreshold.put((byte) 10, (byte) 1);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemGroupsSetup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemGroupsSetup.java
deleted file mode 100644
index 4db104ba..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemGroupsSetup.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.setup;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.ChatColor;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.utils.constant.Strings;
-import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
-
-import dev.sefiraat.sefilib.slimefun.itemgroup.MenuItem;
-import lombok.experimental.UtilityClass;
-
-/**
- * This class setup all item groups.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ItemGroupsSetup {
- public static void setup(@Nonnull SlimefunAddon addon) {
- final MenuItem wikiMenuItem = new MenuItem(BumpItemGroups.WIKI, (p, slot, item, action) -> {
- p.closeInventory();
-
- p.sendMessage("");
- Bump.getLocalization().sendMessage(p, "click-here");
-
- final String lang = Bump.getRegistry().getLanguage();
- if (lang.startsWith("zh")) {
- p.sendMessage(ChatColor.GRAY + Strings.WIKI_CN);
- } else {
- p.sendMessage(ChatColor.GRAY + Strings.WIKI_EN);
- }
-
- p.sendMessage("");
-
- return false;
- });
-
- BumpItemGroups.MAIN.addMenuItem(wikiMenuItem);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.STUFF);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.FOOD);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.MACHINE);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.TOOL);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.ARMOR);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.WEAPON);
- BumpItemGroups.MAIN.addItemGroup(BumpItemGroups.APPRAISE_INFO);
-
- BumpItemGroups.MAIN.register(addon);
-
- BumpItemGroups.STUFF.register(addon);
- BumpItemGroups.FOOD.register(addon);
- BumpItemGroups.MACHINE.register(addon);
- BumpItemGroups.TOOL.register(addon);
- BumpItemGroups.ARMOR.register(addon);
- BumpItemGroups.WEAPON.register(addon);
- BumpItemGroups.APPRAISE_INFO.register(addon);
- BumpItemGroups.HIDDEN.register(addon);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemsSetup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemsSetup.java
deleted file mode 100644
index d5039ecf..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ItemsSetup.java
+++ /dev/null
@@ -1,311 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.setup;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.bakedlibs.dough.items.CustomItemStack;
-import io.github.slimefunguguproject.bump.core.recipes.BumpRecipeTypes;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups;
-import io.github.slimefunguguproject.bump.implementation.items.RandomEquipment;
-import io.github.slimefunguguproject.bump.implementation.items.food.Fangbianmian;
-import io.github.slimefunguguproject.bump.implementation.items.food.Kele;
-import io.github.slimefunguguproject.bump.implementation.items.food.Kouxiangtang;
-import io.github.slimefunguguproject.bump.implementation.items.food.Latiao;
-import io.github.slimefunguguproject.bump.implementation.items.food.Xuebi;
-import io.github.slimefunguguproject.bump.implementation.items.food.Zongzi;
-import io.github.slimefunguguproject.bump.implementation.items.legacy.LegacyAppraisalPaper;
-import io.github.slimefunguguproject.bump.implementation.items.machines.AppraisalInstrument;
-import io.github.slimefunguguproject.bump.implementation.items.machines.AttributeGrindstone;
-import io.github.slimefunguguproject.bump.implementation.items.stuff.StuffItem;
-import io.github.slimefunguguproject.bump.implementation.items.tools.GetgoldSpade;
-import io.github.slimefunguguproject.bump.implementation.items.tools.QualityIdentifier;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.DevilSword;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.LightBow;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.SkyDevilSword;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.SkySword;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.SoulSword;
-import io.github.slimefunguguproject.bump.implementation.items.weapons.WitherSkullBow;
-import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Compressor;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class is used to set up items.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ItemsSetup {
- public static void setup(@Nonnull SlimefunAddon plugin) {
- //
- new RandomEquipment(
- BumpItemGroups.ARMOR,
- BumpItems.RANDOM_HELMET,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- BumpItems.OLD_COIN, null, BumpItems.OLD_COIN,
- BumpItems.OLD_COIN, BumpItems.MAKE, BumpItems.OLD_COIN,
- BumpItems.OLD_COIN, BumpItems.UPDATE_POWER, BumpItems.OLD_COIN
- }
- ).register(plugin);
-
- new RandomEquipment(
- BumpItemGroups.ARMOR,
- BumpItems.RANDOM_HORSE_ARMOR,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- BumpItems.OLD_COIN, null, BumpItems.OLD_COIN,
- BumpItems.OLD_COIN, new ItemStack(Material.DIAMOND_HORSE_ARMOR), BumpItems.OLD_COIN,
- BumpItems.OLD_COIN, BumpItems.UPDATE_POWER, BumpItems.OLD_COIN
- }
- ).register(plugin);
- //
-
- //
- new Xuebi().register(plugin);
- new Kele().register(plugin);
- new Fangbianmian().register(plugin);
- new Latiao().register(plugin);
- new Kouxiangtang().register(plugin);
- new Zongzi().register(plugin);
- //
-
- //
- new AppraisalInstrument().register(plugin);
- new AttributeGrindstone().register(plugin);
- //
-
- //
- new StuffItem(
- BumpItems.SUN_ENERGY,
- RecipeType.MAGIC_WORKBENCH,
- new ItemStack[]{
- new ItemStack(Material.CHORUS_FLOWER), new ItemStack(Material.SUNFLOWER), new ItemStack(Material.CHORUS_FLOWER),
- null, null, null,
- null, null, null
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.MECHA_GEAR,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
- SlimefunItems.COPPER_WIRE, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
- SlimefunItems.ADVANCED_CIRCUIT_BOARD, null, null
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.OLD_COIN,
- BumpRecipeTypes.GETGOLD_SPADE,
- new ItemStack[9]
- ).register(plugin);
-
- new StuffItem(
- BumpItems.MAKE,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- SlimefunItems.BATTERY, SlimefunItems.BATTERY, SlimefunItems.BATTERY,
- SlimefunItems.COOLING_UNIT, SlimefunItems.POWER_CRYSTAL, SlimefunItems.COOLING_UNIT,
- SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.OLD_CPU,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE,
- SlimefunItems.COPPER_WIRE, BumpItems.MAKE, SlimefunItems.COPPER_WIRE,
- SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.CPU,
- RecipeType.COMPRESSOR,
- new ItemStack[]{
- BumpItems.OLD_CPU
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.SOUL_PAPER,
- RecipeType.ANCIENT_ALTAR,
- new ItemStack[]{
- SlimefunItems.MAGIC_LUMP_1, SlimefunItems.ESSENCE_OF_AFTERLIFE, SlimefunItems.MAGIC_LUMP_1,
- SlimefunItems.SOULBOUND_RUNE, SlimefunItems.SOULBOUND_RUNE, SlimefunItems.SOULBOUND_RUNE,
- SlimefunItems.MAGIC_LUMP_1, SlimefunItems.ESSENCE_OF_AFTERLIFE, SlimefunItems.MAGIC_LUMP_1
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.KSF_STUFF,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- SlimefunItems.SALT, SlimefunItems.SALT, SlimefunItems.SALT,
- SlimefunItems.CARROT_FERTILIZER, SlimefunItems.CARROT_FERTILIZER, SlimefunItems.CARROT_FERTILIZER,
- SlimefunItems.SALT, SlimefunItems.SALT, SlimefunItems.SALT
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.WATER_SUGAR,
- RecipeType.PRESSURE_CHAMBER,
- new ItemStack[]{
- SlimefunItems.MAGIC_SUGAR
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.PEACH_WOOD,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- new ItemStack(Material.ACACIA_WOOD), new ItemStack(Material.BIRCH_WOOD), new ItemStack(Material.DARK_OAK_WOOD),
- null, null, null,
- null, null, null
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.UPDATE_POWER,
- RecipeType.MAGIC_WORKBENCH,
- new ItemStack[]{
- SlimefunItems.POWER_CRYSTAL, SlimefunItems.LAVA_CRYSTAL, SlimefunItems.POWER_CRYSTAL,
- SlimefunItems.LAVA_CRYSTAL, BumpItems.CPU, SlimefunItems.LAVA_CRYSTAL,
- SlimefunItems.GOLD_24K, SlimefunItems.GOLD_24K, SlimefunItems.GOLD_24K
- }
- ).register(plugin);
-
- new StuffItem(
- BumpItems.COMPRESSED_RANDOM_EQUIPMENT,
- BumpRecipeTypes.COMPRESSOR_MOCK,
- new ItemStack[]{
- new CustomItemStack(Material.DIAMOND_CHESTPLATE, Bump.getLocalization().getString("lores.any-random-equipment"))
- }
- ).register(plugin);
-
- // compression random equipment
- final SlimefunItem compressorItem = SlimefunItem.getById("COMPRESSOR");
- if (compressorItem instanceof Compressor compressor) {
- compressor.addRecipe(new ItemStack[]{BumpItems.RANDOM_HELMET}, BumpItems.COMPRESSED_RANDOM_EQUIPMENT);
- compressor.addRecipe(new ItemStack[]{BumpItems.RANDOM_SWORD}, BumpItems.COMPRESSED_RANDOM_EQUIPMENT);
- compressor.addRecipe(new ItemStack[]{BumpItems.RANDOM_HORSE_ARMOR}, BumpItems.COMPRESSED_RANDOM_EQUIPMENT);
- }
- //
-
- //
- new GetgoldSpade().register(plugin);
-
- new QualityIdentifier(
- BumpItems.QUALITY_IDENTIFIER,
- RecipeType.SMELTERY,
- new ItemStack[]{
- BumpItems.COMPRESSED_RANDOM_EQUIPMENT
- }
- ).register(plugin);
- //
-
- //
- new LightBow().register(plugin);
- new WitherSkullBow().register(plugin);
-
- new SlimefunItem(
- BumpItemGroups.WEAPON,
- BumpItems.EMER_SWORD,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- null, new ItemStack(Material.EMERALD), null,
- null, new ItemStack(Material.EMERALD), null,
- null, new ItemStack(Material.STICK), null
- }
- ).register(plugin);
-
- new SlimefunItem(
- BumpItemGroups.WEAPON,
- BumpItems.BONE_SWORD,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- null, new ItemStack(Material.BONE_BLOCK, 64), null,
- null, new ItemStack(Material.BONE_BLOCK, 64), null,
- null, SlimefunItems.GRANDMAS_WALKING_STICK, null
- }
- ).register(plugin);
-
- new RandomEquipment(
- BumpItemGroups.WEAPON,
- BumpItems.RANDOM_SWORD,
- RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{
- null, BumpItems.UPDATE_POWER, null,
- null, BumpItems.MAKE, null,
- null, new ItemStack(Material.STICK), null
- }
- ).register(plugin);
-
- new SlimefunItem(
- BumpItemGroups.WEAPON,
- BumpItems.GUARD_SWORD,
- RecipeType.ARMOR_FORGE,
- new ItemStack[]{
- null, BumpItems.SUN_ENERGY, null,
- null, BumpItems.SUN_ENERGY, null,
- null, new ItemStack(Material.STICK), null
- }
- ).register(plugin);
-
- new SlimefunItem(
- BumpItemGroups.WEAPON,
- BumpItems.PEACH_SWORD,
- RecipeType.ARMOR_FORGE,
- new ItemStack[]{
- null, BumpItems.PEACH_WOOD, null,
- null, BumpItems.PEACH_WOOD, null,
- null, new ItemStack(Material.STICK), null
- }
- ).register(plugin);
-
- new SoulSword().register(plugin);
- new SkySword().register(plugin);
- new DevilSword().register(plugin);
- new SkyDevilSword().register(plugin);
- //
-
- //
-
- // legacy quality identifiers
- new LegacyAppraisalPaper(
- BumpItems.APPRAISAL_PAPER_ARMOR,
- RecipeType.SMELTERY,
- new ItemStack[]{
- BumpItems.RANDOM_HELMET
- }
- ).register(plugin);
-
- new LegacyAppraisalPaper(
- BumpItems.APPRAISAL_PAPER_DAMAGE,
- RecipeType.SMELTERY,
- new ItemStack[]{
- BumpItems.RANDOM_SWORD
- }
- ).register(plugin);
-
- new LegacyAppraisalPaper(
- BumpItems.APPRAISAL_PAPER_HORSE_ARMOR,
- RecipeType.SMELTERY,
- new ItemStack[]{
- BumpItems.RANDOM_HORSE_ARMOR
- }
- ).register(plugin);
- //
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ListenerSetup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ListenerSetup.java
deleted file mode 100644
index 30900631..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ListenerSetup.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.setup;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.plugin.java.JavaPlugin;
-
-import io.github.slimefunguguproject.bump.implementation.listeners.BowShootListener;
-import io.github.slimefunguguproject.bump.implementation.listeners.DragonBreathListener;
-import io.github.slimefunguguproject.bump.implementation.listeners.SkySwordListener;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class setup all Listeners.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ListenerSetup {
- public static void setup(@Nonnull JavaPlugin plugin) {
- plugin.getServer().getPluginManager().registerEvents(new BowShootListener(), plugin);
- plugin.getServer().getPluginManager().registerEvents(new DragonBreathListener(), plugin);
- plugin.getServer().getPluginManager().registerEvents(new SkySwordListener(), plugin);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.java
deleted file mode 100644
index f20ba59b..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.setup;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.implementation.BumpItems;
-import io.github.thebusybiscuit.slimefun4.api.researches.Research;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class is used to set up {@link Research Researches}.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ResearchSetup {
- private static int researchId = 114514;
-
- public static void setup() {
- createResearch("food", 18, BumpItems.XUEBI, BumpItems.KELE, BumpItems.FANGBIANMIAN, BumpItems.LATIAO, BumpItems.KOUXIANGTANG);
- createResearch("random_equipment", 45, BumpItems.RANDOM_HELMET, BumpItems.RANDOM_SWORD, BumpItems.RANDOM_HORSE_ARMOR);
- createResearch("appraise", 70, BumpItems.APPRAISAL, BumpItems.APPRAISAL_PAPER_ARMOR, BumpItems.APPRAISAL_PAPER_DAMAGE, BumpItems.APPRAISAL_PAPER_HORSE_ARMOR, BumpItems.ATTRIBUTE_GRINDSTONE);
- createResearch("stuff", 25, BumpItems.SUN_ENERGY, BumpItems.MECHA_GEAR, BumpItems.MAKE, BumpItems.OLD_CPU, BumpItems.CPU, BumpItems.SOUL_PAPER, BumpItems.KSF_STUFF, BumpItems.WATER_SUGAR, BumpItems.UPDATE_POWER);
- createResearch("old_stuff", 20, BumpItems.OLD_COIN, BumpItems.GETGOLD_SPADE);
- createResearch("bow", 30, BumpItems.LIGHT_BOW, BumpItems.WITHERSKULL_BOW);
- createResearch("peach_sword", 32, BumpItems.PEACH_WOOD, BumpItems.PEACH_SWORD);
- createResearch("normal_sword", 28, BumpItems.EMER_SWORD, BumpItems.BONE_SWORD, BumpItems.GUARD_SWORD);
- createResearch("soul_sword", 20, BumpItems.SOUL_SWORD);
- createResearch("sky_devil", 42, BumpItems.SKY_SWORD, BumpItems.DEVIL_SWORD, BumpItems.SKY_DEVIL_SWORD);
- }
-
- @ParametersAreNonnullByDefault
- private static void createResearch(String key, int cost, ItemStack... itemStacks) {
- new Research(Bump.createKey("research_" + key), ++researchId, Bump.getLocalization().getResearchName("key"), cost)
- .addItems(itemStacks).register();
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.java b/src/main/java/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.java
deleted file mode 100644
index d2b15e67..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package io.github.slimefunguguproject.bump.implementation.tasks;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.entity.Projectile;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-/**
- * The {@link WeaponProjectileTask} is responsible for tracking
- * {@link Projectile} fired from Bump weapons.
- *
- * @author ybw0014
- */
-@SuppressWarnings("ConstantConditions")
-public final class WeaponProjectileTask implements Runnable {
-
- private static WeaponProjectileTask instance;
-
- // This map records each projectile's spawn time
- private final Map projectileMap = new HashMap<>();
- private final int duration;
-
- public WeaponProjectileTask(int duration) {
- instance = this;
- this.duration = duration;
- }
-
- /**
- * This method starts this task
- */
- public static void start() {
- int duration = Bump.getRegistry().getConfig().getInt("weapons.projectile-duration", 0, 60);
- if (duration > 0) {
- Bump.getScheduler().repeat(Slimefun.getTickerTask().getTickRate(), new WeaponProjectileTask(duration));
- }
- }
-
- /**
- * This method will add {@link Projectile} to tracking list.
- *
- * @param projectile the {@link Projectile} to be added.
- */
- public static void track(@Nonnull Projectile projectile) {
- Preconditions.checkArgument(projectile != null, "Projectile cannot not be null.");
- Preconditions.checkState(instance != null, "The task instance cannot be null.");
- instance.trackProjectile(projectile);
- }
-
- @Override
- public void run() {
- int currentTick = Bump.getSlimefunTickCount();
-
- Iterator> it = projectileMap.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = it.next();
- if (entry.getValue() + duration < currentTick) {
- Projectile projectile = entry.getKey();
- if (projectile.isValid()) {
- projectile.remove();
- }
- it.remove();
- }
- }
- }
-
- private void trackProjectile(Projectile projectile) {
- projectileMap.put(projectile, Bump.getSlimefunTickCount());
- PersistentDataAPI.setBoolean(projectile, Keys.PROJECTILE, true);
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/AppraiseUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/AppraiseUtils.java
deleted file mode 100644
index 4bf60798..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/AppraiseUtils.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.ChatColor;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.attribute.AttributeModifier;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.constant.Keys;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-
-import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Utility methods for appraise.
- *
- * @author ybw0014
- * @author haiman233
- */
-@SuppressWarnings("ConstantConditions")
-@UtilityClass
-public final class AppraiseUtils {
- /**
- * Check if the {@link ItemStack} is marked as appraisable,
- * which means it can be used in appraisal instrument.
- *
- * @param itemStack The {@link ItemStack} to be checked.
- *
- * @return Whether the {@link ItemStack} is marked as appraisable.
- */
- public static boolean isAppraisable(@Nonnull ItemStack itemStack) {
- if (ValidateUtils.noAirItem(itemStack)) {
- return PersistentDataAPI.getBoolean(itemStack.getItemMeta(), Keys.APPRAISABLE);
- } else {
- return false;
- }
- }
-
- /**
- * Set the {@link ItemStack} as appraisable in appraisal instrument
- *
- * @param itemStack the {@link ItemStack} to be set
- */
- public static void setAppraisable(@Nonnull ItemStack itemStack) {
- if (!ValidateUtils.noAirItem(itemStack)) {
- return;
- }
-
- ItemMeta im = itemStack.getItemMeta();
-
- // set lore
- List lore;
- if (im.hasLore()) {
- lore = im.getLore();
- } else {
- lore = new ArrayList<>();
- }
- lore.add("");
- lore.add(ChatUtil.color(Bump.getLocalization().getString("lores.not-appraised")));
- im.setLore(lore);
-
- // set pdc
- PersistentDataAPI.setBoolean(im, Keys.APPRAISABLE, true);
-
- itemStack.setItemMeta(im);
- }
-
- /**
- * Check if the {@link ItemStack} is appraised
- *
- * @param itemStack the {@link ItemStack} to be checked
- *
- * @return if the {@link ItemStack} is appraised
- */
- public static boolean isAppraised(@Nonnull ItemStack itemStack) {
- if (ValidateUtils.noAirItem(itemStack)) {
- return PersistentDataAPI.hasByte(itemStack.getItemMeta(), Keys.APPRAISE_LEVEL);
- } else {
- return false;
- }
- }
-
- @Nonnull
- public static AttributeModifier.Operation getOperation(@Nonnull Attribute attribute) {
- Preconditions.checkArgument(attribute != null, "Attribute cannot be null");
-
- return switch (attribute) {
- case GENERIC_MOVEMENT_SPEED, HORSE_JUMP_STRENGTH -> AttributeModifier.Operation.ADD_SCALAR;
- default -> AttributeModifier.Operation.ADD_NUMBER;
- };
- }
-
- @Nonnull
- public static List getDescriptionLore(@Nonnull AppraiseType type) {
- Preconditions.checkArgument(type != null, "Appraise type cannot be null");
-
- return type.getDescription().stream()
- .map(line -> ChatUtil.color(ChatColor.GRAY + line))
- .collect(Collectors.toList());
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/ConfigUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/ConfigUtils.java
deleted file mode 100644
index b9c188e4..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/ConfigUtils.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.configuration.Configuration;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.inventory.EquipmentSlot;
-
-import io.github.slimefunguguproject.bump.utils.constant.Patterns;
-import io.github.slimefunguguproject.bump.utils.tags.BumpTag;
-import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.common.CommonPatterns;
-
-import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This utility class contains methods about configuration files.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ConfigUtils {
- /**
- * Add the missing config options in {@link AddonConfig}.
- *
- * @param config The {@link AddonConfig} to deal with.
- */
- public static void addMissingOptions(AddonConfig config) {
- Configuration defaultConfig = config.getDefaults();
- for (String key : defaultConfig.getKeys(true)) {
- if (!config.contains(key)) {
- config.set(key, defaultConfig.get(key));
- }
- }
- }
-
- /**
- * This method will parse {@link List} of material {@link String} into
- * {@link Set} of {@link Material}.
- *
- * Acceptable elements: minecraft materials, bump tags.
- *
- * @param materialList The {@link List} of material {@link String} to be parsed.
- *
- * @return The parsed {@link Set} of {@link Material}.
- *
- * @throws IllegalArgumentException when the list is {@code null} or contains null elements.
- * @throws InvalidConfigurationException when the list contains invalid material or BumpTag.
- * @see BumpTag
- */
- @Nonnull
- public static Set parseMaterials(@Nonnull List materialList) throws InvalidConfigurationException {
- Validate.noNullElements(materialList);
-
- Set materials = new HashSet<>();
- for (String value : materialList) {
- if (Patterns.MINECRAFT_NAMESPACEDKEY.matcher(value).matches()) {
- Material material = Material.matchMaterial(value);
-
- if (material != null) {
- materials.add(material);
- } else {
- throw new InvalidConfigurationException("Invalid minecraft material: " + value);
- }
- } else if (Patterns.BUMP_TAG_CONFIG.matcher(value).matches()) {
- String keyValue = CommonPatterns.COLON.split(value)[1].toUpperCase(Locale.ROOT);
- BumpTag tag = BumpTag.getTag(keyValue);
-
- if (tag != null) {
- materials.addAll(tag.getValues());
- } else {
- throw new InvalidConfigurationException("Invalid BumpTag: " + keyValue);
- }
- }
- }
- return materials;
- }
-
- /**
- * This method will parse {@link List} of equipment slot {@link String} into
- * {@link Set} of {@link EquipmentSlot}.
- *
- * @param slotList The {@link List} of equipment slot {@link String} to be parsed.
- *
- * @return The parsed {@link Set} of {@link EquipmentSlot}.
- *
- * @throws IllegalArgumentException when the list is {@code null} or contains null elements.
- * @throws InvalidConfigurationException when the list contains invalid EquipmentSlot.
- */
- @Nonnull
- public static Set parseEquipmentSlots(@Nonnull List slotList) throws InvalidConfigurationException {
- Validate.noNullElements(slotList);
-
- Set equipmentSlots = new HashSet<>();
- for (String value : slotList) {
- try {
- EquipmentSlot slot = EquipmentSlot.valueOf(value.toUpperCase(Locale.ROOT));
- equipmentSlots.add(slot);
- } catch (IllegalArgumentException ex) {
- throw new InvalidConfigurationException("Invalid EquipmentSlot value: " + value);
- }
- }
- return equipmentSlots;
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.java
deleted file mode 100644
index 43085022..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import org.bukkit.Bukkit;
-import org.bukkit.GameMode;
-import org.bukkit.entity.Player;
-import org.bukkit.event.entity.FoodLevelChangeEvent;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Utility methods about player's food level.
- *
- * @author ybw0014
- */
-@UtilityClass
-public class FoodLevelUtils {
- /**
- * This method calls {@link FoodLevelChangeEvent} and add {@link Player}'s
- * food level if {@link Player}'s {@link GameMode} is not creative and
- * the event is not cancelled
- *
- * @param p the {@link Player} that food level will be changed
- * @param level the level to be added
- *
- * @return if the food level is added
- */
- public static boolean add(Player p, int level) {
- int newLevel = Math.min(20, p.getFoodLevel() + level);
- return set(p, newLevel);
- }
-
- /**
- * This method calls {@link FoodLevelChangeEvent} and set {@link Player}'s
- * food level if {@link Player}'s {@link GameMode} is not creative and
- * the event is not cancelled
- *
- * @param p the {@link Player} that food level will be changed
- * @param level the target food level
- *
- * @return if the food level is changed
- */
- public static boolean set(Player p, int level) {
- if (p.getGameMode() != GameMode.CREATIVE) {
- FoodLevelChangeEvent event = new FoodLevelChangeEvent(p, level);
- Bukkit.getPluginManager().callEvent(event);
-
- if (!event.isCancelled()) {
- p.setFoodLevel(event.getFoodLevel());
- return true;
- }
-
- return false;
- } else {
- return true;
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/GuiItems.java b/src/main/java/io/github/slimefunguguproject/bump/utils/GuiItems.java
deleted file mode 100644
index 4602a2c6..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/GuiItems.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.slimefunguguproject.bump.api.appraise.AppraiseType;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Some GUI items.
- *
- * @author ybw0014
- */
-@UtilityClass
-@SuppressWarnings("ConstantConditions")
-public final class GuiItems {
- public static final ItemStack APPRAISE_BUTTON = new CustomItemStack(
- Material.NAME_TAG,
- Bump.getLocalization().getString("gui.appraise.name"),
- Bump.getLocalization().getStringArray("gui.appraise.lore")
- );
- public static final ItemStack APPRAISE_PAPER = new CustomItemStack(
- Material.PAPER,
- Bump.getLocalization().getString("gui.appraisal_paper.name"),
- Bump.getLocalization().getStringArray("gui.appraisal_paper.lore")
- );
- public static final ItemStack GRIND_BUTTON = new CustomItemStack(
- Material.GRINDSTONE,
- Bump.getLocalization().getString("gui.grind.name"),
- Bump.getLocalization().getStringArray("gui.grind.lore")
- );
-
- @Nonnull
- public static ItemStack appraiseTypeSelector(@Nonnull AppraiseType type) {
- Preconditions.checkArgument(type != null, "Appraise type cannot be null");
-
- List lore = AppraiseUtils.getDescriptionLore(type);
- lore.addAll(Bump.getLocalization().getStringList("gui.appraise_type_selector.lore"));
-
- return new CustomItemStack(
- Material.MAP,
- Bump.getLocalization().getString("gui.appraise_type_selector.name", type.getName()),
- lore
- );
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/JsonUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/JsonUtils.java
deleted file mode 100644
index f42ec466..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/JsonUtils.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import javax.annotation.Nonnull;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-import com.google.gson.stream.JsonReader;
-
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Utility methods for json parsing.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class JsonUtils {
- /**
- * This method parses JSON from the {@link JsonReader}.
- *
- * @param reader The {@link JsonReader} to be read JSON from.
- *
- * @return The root {@link JsonElement}
- */
- public static JsonElement parseReader(@Nonnull JsonReader reader) {
- if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_18)) {
- return JsonParser.parseReader(reader);
- } else {
- return new JsonParser().parse(reader);
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/Utils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/Utils.java
deleted file mode 100644
index 3c0684f8..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/Utils.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import java.lang.reflect.InvocationTargetException;
-
-import javax.annotation.Nonnull;
-
-import org.bukkit.Material;
-import org.bukkit.enchantments.Enchantment;
-import org.bukkit.inventory.ItemFlag;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import net.guizhanss.guizhanlib.utils.StringUtil;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Common utilities.
- *
- * @author ybw0014
- */
-@UtilityClass
-@SuppressWarnings("ConstantConditions")
-public final class Utils {
- /**
- * Get a {@link String} of consecutive stars, maximum at 10.
- *
- * When there are over 10 stars, returns number + star.
- *
- * @param n The number of stars
- *
- * @return {@link String} of consecutive stars.
- */
- @Nonnull
- public static String getStars(int n) {
- if (n <= 10) {
- StringBuilder builder = new StringBuilder();
- while (n > 0) {
- builder.append("⭐");
- n--;
- }
- return builder.toString();
- } else {
- return n + " ⭐";
- }
- }
-
- /**
- * Make the {@link ItemStack} glow.
- *
- * @param item The {@link ItemStack} to be dealt with.
- */
- public static void glowItem(@Nonnull ItemStack item) {
- if (!ValidateUtils.noAirItem(item)) {
- return;
- }
-
- final ItemMeta itemMeta = item.getItemMeta();
- itemMeta.addEnchant(Enchantment.LUCK, 1, true);
- itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
- item.setItemMeta(itemMeta);
- }
-
- /**
- * Get the {@link Material} name.
- *
- * @param material The {@link Material}.
- *
- * @return The material name in Simplified Chinese if GuizhanLibPlugin exists. Otherwise, in English.
- */
- public static String getMaterialName(@Nonnull Material material) {
- try {
- Class> clazz = Class.forName("net.guizhanss.guizhanlib.minecraft.helper.MaterialHelper");
- Object result = clazz.getMethod("getName", Material.class).invoke(null, material);
- return String.valueOf(result);
- } catch (ClassNotFoundException | NoSuchMethodException | NullPointerException
- | IllegalAccessException | InvocationTargetException e) {
- return StringUtil.humanize(material.toString());
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/ValidateUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/ValidateUtils.java
deleted file mode 100644
index 48756b03..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/ValidateUtils.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import javax.annotation.Nullable;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.inventory.ItemStack;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This utility class holds validation methods.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class ValidateUtils {
- /**
- * Validate the given {@link ItemStack} is not {@code null} or an air item.
- *
- * @param itemStack The {@link ItemStack} to be validated.
- *
- * @return if the {@link ItemStack} is valid.
- */
- public static boolean noAirItem(@Nullable ItemStack itemStack) {
- try {
- Preconditions.checkArgument(itemStack != null, "ItemStack cannot be null");
- Preconditions.checkArgument(!itemStack.getType().isAir(), "ItemStack cannot be empty");
- return true;
- } catch (IllegalArgumentException ex) {
- return false;
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/WikiUtils.java b/src/main/java/io/github/slimefunguguproject/bump/utils/WikiUtils.java
deleted file mode 100644
index e2f61a7a..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/WikiUtils.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.github.slimefunguguproject.bump.utils;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.logging.Level;
-
-import org.bukkit.plugin.Plugin;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * These utility methods are responsible to set up the wiki pages for Simplified Chinese Slimefun.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class WikiUtils {
- public static void setupJson() {
- try {
- Class> clazz = Class.forName("net.guizhanss.slimefun4.utils.WikiUtils");
- clazz.getMethod("setupJson", Plugin.class).invoke(null, Bump.getInstance());
- } catch (ClassNotFoundException | NoSuchMethodException | NullPointerException
- | IllegalAccessException | InvocationTargetException e) {
- Bump.log(Level.WARNING, "Cannot load wiki pages. You can safely ignore this message if you are using Official Slimefun DEV/RC version.");
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Keys.java b/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Keys.java
deleted file mode 100644
index af5f8d7f..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Keys.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.slimefunguguproject.bump.utils.constant;
-
-import org.bukkit.NamespacedKey;
-
-import io.github.slimefunguguproject.bump.implementation.Bump;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Some reusable {@link NamespacedKey Namespaced Keys}.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class Keys {
- public static final NamespacedKey APPRAISABLE = Bump.createKey("appraisable");
- public static final NamespacedKey APPRAISE_LEVEL = Bump.createKey("appraise_level");
- public static final NamespacedKey APPRAISE_VERSION = Bump.createKey("appraise_level");
- public static final NamespacedKey LAST_USED = Bump.createKey("last_used");
- public static final NamespacedKey SKY_SWORD_PROTECTED = Bump.createKey("sky_sword_protected");
- public static final NamespacedKey PROJECTILE = Bump.createKey("projectile");
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Patterns.java b/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Patterns.java
deleted file mode 100644
index 0cd48556..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Patterns.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.github.slimefunguguproject.bump.utils.constant;
-
-import java.util.regex.Pattern;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * This class contains some {@link Pattern} used in Bump.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class Patterns {
- public static final Pattern MINECRAFT_NAMESPACEDKEY = Pattern.compile("minecraft:[a-z0-9/._-]+");
- public static final Pattern BUMP_TAG = Pattern.compile("#bump:[a-z_]+");
- public static final Pattern BUMP_TAG_CONFIG = Pattern.compile("bump:[a-z_]+");
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Strings.java b/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Strings.java
deleted file mode 100644
index ee794c7d..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/constant/Strings.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.github.slimefunguguproject.bump.utils.constant;
-
-import org.bukkit.ChatColor;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * Some strings used in Bump.
- *
- * @author ybw0014
- */
-@UtilityClass
-public final class Strings {
- public static final String CHECK = ChatColor.GREEN + "✔";
- public static final String CROSS = ChatColor.RED + "✘";
-
- public static final String WIKI_EN = "https://bump.ybw0014.dev/";
- public static final String WIKI_CN = "https://slimefun-addons-wiki.guizhanss.cn/bump/";
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/tags/BumpTag.java b/src/main/java/io/github/slimefunguguproject/bump/utils/tags/BumpTag.java
deleted file mode 100644
index f13d8681..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/tags/BumpTag.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package io.github.slimefunguguproject.bump.utils.tags;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
-import org.bukkit.Tag;
-
-import io.github.slimefunguguproject.bump.api.exceptions.TagMisconfigurationException;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-
-/**
- * Tags for some materials.
- *
- * @author ybw0014
- * @author haiman233
- */
-@SuppressWarnings("ConstantConditions")
-public enum BumpTag implements Tag {
- /**
- * This includes all swords.
- */
- SWORD,
-
- /**
- * This includes all helmets.
- */
- HELMET,
-
- /**
- * This includes all chestplates.
- */
- CHESTPLATE,
-
- /**
- * This includes all leggings.
- */
- LEGGINGS,
-
- /**
- * This includes all boots.
- */
- BOOTS,
-
- /**
- * This includes all horse armors.
- */
- HORSE_ARMOR,
-
- /**
- * This includes all axes.
- */
- AXE,
-
- /**
- * This includes all pickaxes.
- */
- PICKAXE,
-
- /**
- * This includes all shovels.
- */
- SHOVEL,
-
- /**
- * This includes all hoes.
- */
- HOE,
-
- /**
- * This includes all fishing rods.
- */
- FISHING_ROD,
-
- /**
- * This includes all bows.
- */
- BOW,
-
- /**
- * This includes all kinds of heads.
- */
- HEAD,
-
- /**
- * This includes all carpets.
- */
- CARPET,
-
- /**
- * This includes all materials that is suitable for main hand slot.
- */
- HAND_SLOT,
-
- /**
- * This includes all materials that is suitable for off hand slot.
- */
- OFF_HAND_SLOT,
-
- /**
- * This includes all materials that is suitable for head slot.
- */
- HEAD_SLOT,
-
- /**
- * This includes all materials that is suitable for chest slot.
- */
- CHEST_SLOT,
-
- /**
- * This includes all materials that is suitable for legs slot.
- */
- LEGS_SLOT,
-
- /**
- * This includes all materials that is suitable for feet slot.
- */
- FEET_SLOT;
-
- /**
- * Cached values.
- */
- private static final BumpTag[] cachedValues = values();
-
- /**
- * Lookup table for tag names.
- */
- private static final Map nameLookup = new HashMap<>();
-
- static {
- for (BumpTag tag : cachedValues) {
- nameLookup.put(tag.name(), tag);
- }
- }
-
- private final NamespacedKey key;
- private final Set materials = new HashSet<>();
- private final Set> additionalTags = new HashSet<>();
-
- BumpTag() {
- this.key = Bump.createKey(name().toLowerCase(Locale.ROOT));
- }
-
- /**
- * Reload all tags.
- */
- public static void reloadAll() {
- for (BumpTag tag : cachedValues) {
- tag.reload();
- }
- }
-
- /**
- * Get the {@link BumpTag} with specified name.
- *
- * @param value The name of {@link BumpTag}.
- *
- * @return The {@link BumpTag}. Null if name doesn't exist.
- */
- @Nullable
- public static BumpTag getTag(@Nonnull String value) {
- Preconditions.checkArgument(value != null, "Tag cannot be null!");
-
- return nameLookup.get(value);
- }
-
- /**
- * Reload this {@link BumpTag} from resources.
- */
- public void reload() {
- try {
- new TagParser(this).parse((materialSet, additionalTagSet) -> {
- materials.clear();
- materials.addAll(materialSet);
-
- additionalTags.clear();
- additionalTags.addAll(additionalTagSet);
- });
- } catch (TagMisconfigurationException ex) {
- Bump.log(Level.SEVERE, ex, "An error has occurred while trying to load Bump tag: " + name());
- }
- }
-
- @Nonnull
- @Override
- public NamespacedKey getKey() {
- return this.key;
- }
-
- @Override
- public boolean isTagged(@Nonnull Material material) {
- if (materials.contains(material)) {
- return true;
- } else {
- for (Tag tag : additionalTags) {
- if (tag.isTagged(material)) {
- return true;
- }
- }
-
- return false;
- }
- }
-
- @Nonnull
- @Override
- public Set getValues() {
- if (additionalTags.isEmpty()) {
- return Collections.unmodifiableSet(materials);
- } else {
- Set values = EnumSet.noneOf(Material.class);
- values.addAll(materials);
-
- for (Tag tag : additionalTags) {
- values.addAll(tag.getValues());
- }
-
- return values;
- }
- }
-
- public boolean isEmpty() {
- if (!materials.isEmpty()) {
- return false;
- } else {
- return getValues().isEmpty();
- }
- }
-}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/utils/tags/TagParser.java b/src/main/java/io/github/slimefunguguproject/bump/utils/tags/TagParser.java
deleted file mode 100644
index 3d38c483..00000000
--- a/src/main/java/io/github/slimefunguguproject/bump/utils/tags/TagParser.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package io.github.slimefunguguproject.bump.utils.tags;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.function.BiConsumer;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.stream.JsonReader;
-
-import org.bukkit.Keyed;
-import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
-import org.bukkit.Tag;
-
-import io.github.slimefunguguproject.bump.api.exceptions.TagMisconfigurationException;
-import io.github.slimefunguguproject.bump.implementation.Bump;
-import io.github.slimefunguguproject.bump.utils.JsonUtils;
-import io.github.slimefunguguproject.bump.utils.constant.Patterns;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.common.CommonPatterns;
-
-/**
- * The {@link TagParser} is responsible for parsing a JSON file into a {@link BumpTag}.
- *
- * @author ybw0014
- * @see BumpTag
- */
-class TagParser implements Keyed {
- /**
- * Every {@link Tag} has a {@link NamespacedKey}.
- * This is the {@link NamespacedKey} for the resulting {@link Tag}.
- */
- private final NamespacedKey key;
-
- /**
- * This constructs a new {@link TagParser} for the given {@link BumpTag}
- *
- * @param tag The {@link BumpTag} to parse inputs for.
- */
- TagParser(@Nonnull BumpTag tag) {
- this.key = tag.getKey();
- }
-
- /**
- * This will parse the JSON and run the provided callback with {@link Set Sets} of
- * matched {@link Material Materials} and {@link Tag Tags}.
- *
- * @param callback A callback to run after successfully parsing the input.
- *
- * @throws TagMisconfigurationException This is thrown whenever the given input is malformed or no adequate
- * {@link Material} or {@link Tag} could be found
- */
- public void parse(@Nonnull BiConsumer, Set>> callback) throws TagMisconfigurationException {
- String path = "/tags/" + key.getKey() + ".json";
- Set materials = EnumSet.noneOf(Material.class);
- Set> tags = new HashSet<>();
-
- try {
- final InputStream stream = Bump.class.getResourceAsStream(path);
- JsonReader reader = new JsonReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
- JsonObject root = JsonUtils.parseReader(reader).getAsJsonObject();
- JsonElement child = root.get("values");
-
- if (child instanceof JsonArray) {
- JsonArray values = child.getAsJsonArray();
-
- for (JsonElement element : values) {
- if (element instanceof JsonPrimitive primitive && primitive.isString()) {
- parseString(element.getAsString(), materials, tags);
- } else {
- throw new TagMisconfigurationException(key, "Unexpected value format: " + element.getClass().getSimpleName() + " - " + element);
- }
- }
-
- callback.accept(materials, tags);
- } else {
- throw new TagMisconfigurationException(key, "No values array specified");
- }
- } catch (NullPointerException | IllegalStateException | JsonParseException x) {
- throw new TagMisconfigurationException(key, x);
- }
- }
-
- @ParametersAreNonnullByDefault
- private void parseString(String value, Set materials, Set> tags) throws TagMisconfigurationException {
- if (Patterns.MINECRAFT_NAMESPACEDKEY.matcher(value).matches()) {
- Material material = Material.matchMaterial(value);
-
- if (material != null) {
- materials.add(material);
- }
- } else if (Patterns.BUMP_TAG.matcher(value).matches()) {
- String keyValue = CommonPatterns.COLON.split(value)[1].toUpperCase(Locale.ROOT);
- BumpTag tag = BumpTag.getTag(keyValue);
-
- if (tag != null) {
- tags.add(tag);
- } else {
- throw new TagMisconfigurationException(key, "Bump tag not exist: " + keyValue);
- }
- }
- }
-
- @Nonnull
- @Override
- public NamespacedKey getKey() {
- return key;
- }
-}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/Bump.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/Bump.kt
new file mode 100644
index 00000000..f3b6fe32
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/Bump.kt
@@ -0,0 +1,158 @@
+package io.github.slimefunguguproject.bump
+
+import io.github.slimefunguguproject.bump.core.services.ConfigService
+import io.github.slimefunguguproject.bump.core.services.IntegrationService
+import io.github.slimefunguguproject.bump.core.services.ListenerService
+import io.github.slimefunguguproject.bump.core.services.LocalizationService
+import io.github.slimefunguguproject.bump.core.services.sounds.SoundService
+import io.github.slimefunguguproject.bump.implementation.BumpItems
+import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups
+import io.github.slimefunguguproject.bump.implementation.setup.AppraiseSetup
+import io.github.slimefunguguproject.bump.implementation.setup.ResearchSetup
+import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask
+import io.github.slimefunguguproject.bump.utils.WikiUtils
+import io.github.slimefunguguproject.bump.utils.tags.BumpTag
+import net.byteflux.libby.BukkitLibraryManager
+import net.byteflux.libby.Library
+import net.guizhanss.guizhanlib.slimefun.addon.AbstractAddon
+import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig
+import org.bstats.bukkit.Metrics
+import org.bstats.charts.SimplePie
+import org.bukkit.Bukkit
+import java.util.logging.Level
+
+class Bump : AbstractAddon(
+ "SlimefunGuguProject", "Bump", "main", "options.auto-update"
+) {
+
+ override fun load() {
+ // check if there is central repo prop defined
+ val centralRepo = System.getProperty("centralRepository") ?: "https://repo1.maven.org/maven2/"
+
+ logger.info("Loading libraries, please wait...")
+ logger.info("If you stuck here for a long time (>30s), try to specify a mirror repository by adding -DcentralRepository= to your JVM arguments.")
+
+ // download libs
+ val manager = BukkitLibraryManager(this, "libraries")
+ manager.addRepository(centralRepo)
+ manager.loadLibrary(
+ Library.builder().groupId("org.jetbrains.kotlin").artifactId("kotlin-stdlib").version("2.0.20").build()
+ )
+ manager.loadLibrary(
+ Library.builder().groupId("org.jetbrains.kotlin").artifactId("kotlin-reflect").version("2.0.20").build()
+ )
+
+ logger.info("Loaded all required libraries.")
+ }
+
+ override fun enable() {
+ instance = this
+
+ sendConsole("&6&l____ ")
+ sendConsole("&6&l | _ \\ ")
+ sendConsole("&6&l | |_) |_ _ _ __ ___ _ __ ")
+ sendConsole("&6&l | _ <| | | | '_ ` _ \\| '_ \\ ")
+ sendConsole("&6&l | |_) | |_| | | | | | | |_) |")
+ sendConsole("&6&l |____/ \\__,_|_| |_| |_| .__/ ")
+ sendConsole("&6&l | | ")
+ sendConsole("&6&l |_| ")
+
+
+ sendConsole("&a&l Bump 3 for Slimefun4 RC-37+")
+ sendConsole("&a&l Powered By bxx2004, SlimefunGuguProject")
+ sendConsole("&a&l GitHub: https://github.com/SlimefunGuguProject/Bump")
+ sendConsole("&a&l Issues: https://github.com/SlimefunGuguProject/Bump/issues")
+
+ // config
+ configService = ConfigService(this)
+
+ // localization
+ log(Level.INFO, "Loading language...")
+ val lang = configService.lang
+ localization = LocalizationService(this, file)
+ localization.idPrefix = "BUMP_"
+ localization.addLanguage(lang)
+ if (lang != DEFAULT_LANG) {
+ localization.addLanguage(DEFAULT_LANG)
+ }
+ log(Level.INFO, "Loaded language {0}.", lang)
+
+ // tags
+ BumpTag.reloadAll()
+
+ // sound service
+ soundService = SoundService(AddonConfig("sounds.yml"))
+ soundService.load(true)
+
+ // appraise setup
+ AppraiseSetup.setup()
+
+ // item groups setup
+ BumpItemGroups.setup()
+
+ // item setup
+ BumpItems
+
+ // researches setup
+ if (configService.enableResearches) {
+ ResearchSetup.setup()
+ }
+
+ // wiki setup
+ WikiUtils.setupJson()
+
+ // listeners
+ ListenerService(this)
+
+ // tasks
+ WeaponProjectileTask.start()
+
+ // Metrics setup
+ setupMetrics()
+ }
+
+ override fun disable() {
+ Bukkit.getScheduler().cancelTasks(this)
+ }
+
+ private fun setupMetrics() {
+ val metrics = Metrics(this, 14870)
+ metrics.addCustomChart(SimplePie("server_language") { configService.lang })
+ metrics.addCustomChart(SimplePie("enable_research") { if (configService.enableResearches) "enabled" else "disabled" })
+ }
+
+ companion object {
+
+ const val DEFAULT_LANG = "en"
+
+ lateinit var instance: Bump
+ private set
+ lateinit var configService: ConfigService
+ private set
+ lateinit var localization: LocalizationService
+ private set
+ lateinit var soundService: SoundService
+ private set
+ lateinit var integrationService: IntegrationService
+ private set
+
+ fun scheduler() = getScheduler()
+
+ fun sfTickCount() = getSlimefunTickCount()
+
+ fun log(level: Level, message: String) {
+ instance.logger.log(level, message)
+ }
+
+ fun log(level: Level, ex: Throwable, message: String) {
+ instance.logger.log(level, ex) { message }
+ }
+
+ fun debug(message: String) {
+ if (!Companion::configService.isInitialized || !configService.debug) {
+ return
+ }
+ log(Level.INFO, "[DEBUG] $message")
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.kt
new file mode 100644
index 00000000..57396e8b
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseAttribute.kt
@@ -0,0 +1,62 @@
+package io.github.slimefunguguproject.bump.api.appraise
+
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier.Operation
+
+data class AppraiseAttribute(
+ val attribute: Attribute,
+ val min: Double,
+ val max: Double,
+ val operation: Operation = Operation.ADD_NUMBER
+) {
+
+ constructor(
+ attribute: Attribute,
+ min: Double,
+ max: Double,
+ weight: Double,
+ operation: Operation = Operation.ADD_NUMBER
+ ) : this(attribute, min, max, operation) {
+ this.weight = weight
+ }
+
+ init {
+ if (min > max) error("Min value cannot be greater than max value.")
+ }
+
+ /**
+ * The weight is meant to set on init, or not set and will be calculated later.
+ */
+ var weight: Double = UNSET_WEIGHT
+ set(value) {
+ require(value == UNSET_WEIGHT || value in 0.0..100.0) { "Weight must be between 0 and 100." }
+ require(field < 0.0) { "Cannot set weight after the weight is already set." }
+ field = value
+ }
+
+ override fun toString() =
+ "AppraiseAttribute(attribute=$attribute, min=$min, max=$max, weight=$weight, operation=$operation)"
+
+ /**
+ * Get the percent of result [value] within range.
+ */
+ fun getPercent(value: Double): Double {
+ return if (value <= min) {
+ 0.0
+ } else if (value >= max) {
+ 100.0
+ } else {
+ (value - min) / (max - min) * 100.0
+ }
+ }
+
+ /**
+ * Get the weighted percent of result [value].
+ */
+ fun getWeightedPercent(value: Double) = getPercent(value) * weight / 100.0
+
+ companion object {
+
+ const val UNSET_WEIGHT = -1.0
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.kt
new file mode 100644
index 00000000..c800615f
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseResult.kt
@@ -0,0 +1,95 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.api.appraise
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.slimefunguguproject.bump.utils.GeneralUtils
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils.getOperation
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils.noAirItem
+import io.github.slimefunguguproject.bump.utils.tags.BumpTag
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import org.bukkit.attribute.AttributeModifier
+import org.bukkit.inventory.ItemStack
+import java.util.UUID
+
+class AppraiseResult private constructor(
+ val type: AppraiseType,
+ val result: Map,
+) {
+
+ var totalPercent = 0.0
+ private set
+
+ init {
+ for (entry in result.entries) {
+ totalPercent += entry.key.getWeightedPercent(entry.value)
+ }
+ }
+
+ class Builder(private val type: AppraiseType) {
+
+ private val result: MutableMap = mutableMapOf()
+
+ fun attribute(attribute: AppraiseAttribute, value: Double) = apply { result[attribute] = value }
+
+ fun build() = AppraiseResult(type, result)
+ }
+
+ fun getStars(): Byte {
+ for ((key, value) in BumpRegistry.starThresholds.entries) {
+ if (totalPercent >= key) {
+ return value
+ }
+ }
+ return 0
+ }
+
+ fun apply(itemStack: ItemStack) {
+ require(noAirItem(itemStack)) { "ItemStack cannot be null or air." }
+ val meta = itemStack.itemMeta!!
+ val material = itemStack.type
+ val stars = getStars()
+
+ // attributes
+ for ((key, value) in result) {
+ val attr = key.attribute
+
+ for (slot in type.validEquipmentSlots) {
+ // Check if the material is applicable for slot
+ val tag = BumpTag.getTag(slot.name + "_SLOT")!!
+ if (tag.isTagged(material)) {
+ meta.addAttributeModifier(
+ attr,
+ AttributeModifier(UUID.randomUUID(), type.key.toString(), value, getOperation(attr), slot)
+ )
+ }
+ }
+ }
+
+ // lore
+ val loreLine: String = Bump.localization.getLore("appraised", GeneralUtils.getStars(stars))
+ if (meta.hasLore()) {
+ val lore = meta.lore!!
+ for (i in lore.indices) {
+ if (lore[i] == ChatUtil.color(Bump.localization.getLore("not-appraised"))) {
+ lore[i] = ChatUtil.color(loreLine)
+ break
+ }
+ }
+ meta.lore = lore
+ } else {
+ val lore: MutableList = ArrayList()
+ lore.add(ChatUtil.color(loreLine))
+ meta.lore = lore
+ }
+
+ // pdc
+ PersistentDataAPI.setByte(meta, Keys.APPRAISE_LEVEL, stars)
+ PersistentDataAPI.setByte(meta, Keys.APPRAISE_VERSION, 2.toByte())
+
+ itemStack.setItemMeta(meta)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.kt
new file mode 100644
index 00000000..fb04fbea
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/AppraiseType.kt
@@ -0,0 +1,177 @@
+package io.github.slimefunguguproject.bump.api.appraise
+
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
+import net.guizhanss.guizhanlib.utils.RandomUtil
+import org.bukkit.Material
+import org.bukkit.NamespacedKey
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier.Operation
+import org.bukkit.entity.Player
+import org.bukkit.inventory.EquipmentSlot
+import org.bukkit.inventory.ItemStack
+import javax.annotation.Nonnull
+
+data class AppraiseType internal constructor(
+ val key: NamespacedKey,
+ val name: String,
+ val description: List,
+ val permission: String?,
+ val attributes: Set,
+ val checkMaterial: Boolean,
+ val equipmentType: EquipmentType,
+ val validMaterials: Set,
+ val validEquipmentSlots: Set,
+ val validSlimefunItemIds: Set,
+ val addon: SlimefunAddon,
+) {
+
+ fun hasPermission(p: Player) = permission == null || p.hasPermission(permission)
+
+ /**
+ * This method checks if specified [ItemStack] fit this [AppraiseType].
+ *
+ * @param itemStack The [ItemStack] to be checked.
+ *
+ * @return If the [ItemStack] fit this [AppraiseType].
+ */
+ fun isValidItem(itemStack: ItemStack): Boolean {
+ // Material check
+ if (checkMaterial && !validMaterials.contains(itemStack.type)) {
+ return false
+ }
+
+ // Equipment type check
+ val sfItem = SlimefunItem.getOptionalByItem(itemStack)
+ return when (equipmentType) {
+ EquipmentType.VANILLA -> sfItem.isEmpty
+ EquipmentType.SLIMEFUN -> sfItem.isPresent && isAcceptableSlimefunItem(sfItem.get())
+ EquipmentType.ANY -> sfItem.isEmpty || isAcceptableSlimefunItem(sfItem.get())
+ }
+ }
+
+ fun isAcceptableSlimefunItem(sfItem: SlimefunItem): Boolean {
+ val id = sfItem.id
+ return validSlimefunItemIds.isEmpty() || validSlimefunItemIds.contains(id)
+ }
+
+ /**
+ * This method will generate random values as [AppraiseResult].
+ *
+ * @return The [AppraiseResult].
+ */
+ @Nonnull
+ fun appraise(): AppraiseResult {
+ val builder = AppraiseResult.Builder(this)
+
+ for (attr in attributes) {
+ val value = RandomUtil.randomDouble(attr.min, attr.max)
+ builder.attribute(attr, value)
+ }
+
+ return builder.build()
+ }
+
+ class Builder(
+ private val key: NamespacedKey,
+ ) {
+
+ private var name: String = key.key
+ private var description: List = emptyList()
+ private var permission: String? = null
+ private var attributes: MutableSet = mutableSetOf()
+ private var checkMaterial: Boolean = false
+ private var equipmentType: EquipmentType = EquipmentType.ANY
+ private var validMaterials: MutableSet = mutableSetOf()
+ private var validEquipmentSlots: MutableSet = mutableSetOf()
+ private var validSlimefunItemIds: MutableSet = mutableSetOf()
+
+ private var usedPercent = 0.0
+
+ fun name(name: String) = apply { this.name = name }
+ fun description(description: List) = apply { this.description = description }
+ fun permission(permission: String?) = apply { this.permission = permission }
+ fun attribute(
+ attribute: Attribute,
+ min: Double,
+ max: Double,
+ weight: Double = AppraiseAttribute.UNSET_WEIGHT,
+ operation: Operation = Operation.ADD_NUMBER
+ ) = apply {
+ attributes.add(AppraiseAttribute(attribute, min, max, weight, operation))
+ if (weight != AppraiseAttribute.UNSET_WEIGHT) {
+ usedPercent += weight
+ }
+ }
+
+ fun checkMaterial(checkMaterial: Boolean) = apply { this.checkMaterial = checkMaterial }
+ fun equipmentType(equipmentType: EquipmentType) = apply { this.equipmentType = equipmentType }
+ fun validMaterials(validMaterials: Collection) = apply {
+ for (material in validMaterials) {
+ if (material == Material.AIR) error("Material cannot be AIR.")
+ }
+ this.validMaterials.addAll(validMaterials)
+ }
+
+ fun validEquipmentSlots(validEquipmentSlots: Collection) =
+ apply { this.validEquipmentSlots.addAll(validEquipmentSlots) }
+
+ fun validSlimefunItemIds(validSlimefunItemIds: Collection) =
+ apply { this.validSlimefunItemIds.addAll(validSlimefunItemIds) }
+
+ /**
+ * Build and register.
+ */
+ fun build(addon: SlimefunAddon): AppraiseType {
+ if (BumpRegistry.appraiseTypeKeys.containsKey(key)) {
+ error("AppraiseType with key \"$key\" already exists.")
+ }
+
+ if (usedPercent > 100.0) {
+ error("The sum of weights cannot be greater than 100.")
+ }
+
+ val noWeightAttributes = attributes.filter { it.weight == AppraiseAttribute.UNSET_WEIGHT }
+ val avgPercent = (100.0 - usedPercent) / noWeightAttributes.size
+ for (attribute in noWeightAttributes) {
+ attribute.weight = avgPercent
+ usedPercent += avgPercent
+ }
+
+ if (usedPercent != 100.0) {
+ error("The sum of weights must be 100.")
+ }
+
+ val appraiseType = AppraiseType(
+ key,
+ name,
+ description,
+ permission,
+ attributes,
+ checkMaterial,
+ equipmentType,
+ validMaterials,
+ validEquipmentSlots,
+ validSlimefunItemIds,
+ addon
+ )
+
+ BumpRegistry.appraiseTypeKeys[key] = appraiseType
+ BumpRegistry.appraiseTypes.add(appraiseType)
+
+ return appraiseType
+ }
+ }
+
+ companion object {
+
+ fun getByKey(key: NamespacedKey) = BumpRegistry.appraiseTypeKeys[key]
+ }
+}
+
+enum class EquipmentType {
+ VANILLA,
+ SLIMEFUN,
+ ANY
+}
diff --git a/src/main/java/io/github/slimefunguguproject/bump/api/appraise/package-info.java b/src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/package-info.java
similarity index 100%
rename from src/main/java/io/github/slimefunguguproject/bump/api/appraise/package-info.java
rename to src/main/kotlin/io/github/slimefunguguproject/bump/api/appraise/package-info.java
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.kt
new file mode 100644
index 00000000..dd85501d
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/api/exceptions/TagMisconfigurationException.kt
@@ -0,0 +1,35 @@
+package io.github.slimefunguguproject.bump.api.exceptions
+
+import io.github.slimefunguguproject.bump.utils.tags.BumpTag
+import org.bukkit.NamespacedKey
+import javax.annotation.ParametersAreNonnullByDefault
+
+class TagMisconfigurationException : Exception {
+
+ /**
+ * This constructs a new [TagMisconfigurationException] for the given
+ * [BumpTag]'s [NamespacedKey] with the provided context.
+ *
+ * @param key The [NamespacedKey] of [BumpTag]
+ * @param message The message to display
+ */
+ constructor(key: NamespacedKey, message: String)
+ : super("Tag '$key' has been misconfigured: $message")
+
+ /**
+ * This constructs a new [TagMisconfigurationException] for the given
+ * [BumpTag]'s [NamespacedKey] with the provided context.
+ *
+ * @param key The [NamespacedKey] of [BumpTag]
+ * @param cause The [Throwable] which has caused this to happen
+ */
+ @ParametersAreNonnullByDefault
+ constructor(key: NamespacedKey, cause: Throwable)
+ : super("Tag '" + key + "' has been misconfigured (" + cause.message + ')', cause)
+
+
+ companion object {
+
+ private val serialVersionUID = 1145141919810L
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/BumpRegistry.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/BumpRegistry.kt
new file mode 100644
index 00000000..d2ddf57a
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/BumpRegistry.kt
@@ -0,0 +1,11 @@
+package io.github.slimefunguguproject.bump.core
+
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import org.bukkit.NamespacedKey
+
+object BumpRegistry {
+
+ val appraiseTypeKeys: MutableMap = mutableMapOf()
+ val appraiseTypes: MutableSet = mutableSetOf()
+ val starThresholds: MutableMap = mutableMapOf()
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.kt
new file mode 100644
index 00000000..b2fc4214
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/AppraisableItem.kt
@@ -0,0 +1,8 @@
+package io.github.slimefunguguproject.bump.core.attributes
+
+import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute
+
+/**
+ * Indicates the item can be appraised directly.
+ */
+interface AppraisableItem : ItemAttribute
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.kt
new file mode 100644
index 00000000..a5caca66
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CooldownItem.kt
@@ -0,0 +1,72 @@
+package io.github.slimefunguguproject.bump.core.attributes
+
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils.noAirAndHasItemMeta
+import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import org.bukkit.inventory.ItemStack
+
+interface CooldownItem : ItemAttribute {
+ companion object {
+
+ private const val INVALID_ITEMSTACK = "Invalid ItemStack."
+ }
+
+ /**
+ * This variable returns the cooldown time in seconds.
+ */
+ fun getCooldown(): Int
+
+ /**
+ * Set the [ItemStack] to cooldown.
+ *
+ * @param itemStack The [ItemStack] to be set to cooldown.
+ */
+ fun setCooldown(itemStack: ItemStack) {
+ require(noAirAndHasItemMeta(itemStack)) { INVALID_ITEMSTACK }
+
+ val im = itemStack.itemMeta!!
+ PersistentDataAPI.setLong(im, Keys.LAST_USED, System.currentTimeMillis())
+ itemStack.setItemMeta(im)
+ }
+
+ /**
+ * This method checks if given [ItemStack] has cooled down.
+ *
+ * @param itemStack The [ItemStack] to be checked
+ *
+ * @return if the item can be used now
+ */
+ fun isCooldown(itemStack: ItemStack): Boolean {
+ require(noAirAndHasItemMeta(itemStack)) { INVALID_ITEMSTACK }
+
+ val im = itemStack.itemMeta!!
+
+ return if (PersistentDataAPI.hasLong(im, Keys.LAST_USED)) {
+ val lastUsed = PersistentDataAPI.getLong(im, Keys.LAST_USED)
+
+ lastUsed + getCooldown() * 1000L < System.currentTimeMillis()
+ } else {
+ true
+ }
+ }
+
+ /**
+ * This method checks if given [ItemStack] has cooled down,
+ * if so, set the [ItemStack] to be just used.
+ *
+ * @param itemStack The [ItemStack] to be checked
+ *
+ * @return if the item can be used now
+ */
+ fun checkCooldown(itemStack: ItemStack): Boolean {
+ require(noAirAndHasItemMeta(itemStack)) { INVALID_ITEMSTACK }
+
+ return if (isCooldown(itemStack)) {
+ setCooldown(itemStack)
+ true
+ } else {
+ false
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.kt
new file mode 100644
index 00000000..b137b499
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/attributes/CostHungerItem.kt
@@ -0,0 +1,44 @@
+package io.github.slimefunguguproject.bump.core.attributes
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute
+import org.bukkit.GameMode
+import org.bukkit.entity.Player
+
+interface CostHungerItem : ItemAttribute {
+
+ /**
+ * This variable returns the hunger cost of the item.
+ */
+ fun getHungerCost(): Int
+
+ /**
+ * This method will check whether [Player]'s food level is sufficient to cost.
+ *
+ * @param p the [Player] that uses the item
+ *
+ * @return if player has enough hunger
+ */
+ fun checkHunger(p: Player): Boolean {
+ return if (p.gameMode != GameMode.CREATIVE) {
+ p.foodLevel >= getHungerCost()
+ } else {
+ true
+ }
+ }
+
+ /**
+ * This method will cost hunger of a [Player].
+ *
+ * @param p the [Player] that uses the item
+ *
+ * @return if player has reduced enough hunger
+ */
+ fun costHunger(p: Player): Boolean {
+ return if (checkHunger(p)) {
+ FoodLevelUtils.set(p, p.foodLevel - getHungerCost())
+ } else {
+ false
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.kt
new file mode 100644
index 00000000..7b061962
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/handlers/BowUseHandler.kt
@@ -0,0 +1,26 @@
+package io.github.slimefunguguproject.bump.core.handlers
+
+import io.github.thebusybiscuit.slimefun4.api.exceptions.IncompatibleItemHandlerException
+import io.github.thebusybiscuit.slimefun4.api.items.ItemHandler
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.event.entity.EntityShootBowEvent
+import org.bukkit.inventory.ItemStack
+import java.util.Optional
+
+fun interface BowUseHandler : ItemHandler {
+
+ fun onUse(e: EntityShootBowEvent, p: Player, bow: ItemStack)
+
+ override fun validate(item: SlimefunItem): Optional {
+ if (item.item.type != Material.BOW) {
+ return Optional.of(IncompatibleItemHandlerException("Only bows can have a BowUseHandler.", item, this))
+ }
+
+ return Optional.empty()
+ }
+
+ override fun getIdentifier() = BowUseHandler::class.java
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ConfigService.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ConfigService.kt
new file mode 100644
index 00000000..af6b2ae6
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ConfigService.kt
@@ -0,0 +1,69 @@
+package io.github.slimefunguguproject.bump.core.services
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.ConfigUtils
+import io.github.thebusybiscuit.slimefun4.libraries.dough.config.Config
+import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig
+import org.bukkit.configuration.ConfigurationSection
+
+class ConfigService(private val plugin: Bump) {
+
+ private var config: AddonConfig = AddonConfig(plugin, "config.yml")
+ private var appraiseConfig: Config = Config(plugin, "appraise.yml")
+
+ var autoUpdate = true
+ private set
+ var debug = false
+ private set
+ var lang = "en"
+ private set
+ var enableResearches = true
+ private set
+ var weaponProjectileDuration = 10
+ private set
+ var appraiserBroadcastEnabled = true
+ private set
+ var appraiserBroadcastStarRequirement = 7
+ private set
+ var appraiseStars: Map = mapOf()
+ private set
+ var appraiseTypes: ConfigurationSection? = null
+ private set
+
+ init {
+ reload()
+ }
+
+ fun reload() {
+ config.reload()
+ config.addMissingKeys()
+ ConfigUtils.saveDefaultFile(plugin, "appraise.yml")
+ appraiseConfig.reload()
+
+ // config.yml
+ autoUpdate = config.getBoolean("auto-update", true)
+ debug = config.getBoolean("debug", false)
+ lang = config.getString("lang", "en")!!
+ enableResearches = config.getBoolean("enable-researches", true)
+ weaponProjectileDuration = config.getInt("weapons.projectile-duration", 10)
+ appraiserBroadcastEnabled = config.getBoolean("appraiser.broadcast.enabled", true)
+ appraiserBroadcastStarRequirement = config.getInt("appraiser.broadcast.star-requirement", 7)
+
+ // appraise.yml
+ appraiseTypes = appraiseConfig.configuration.getConfigurationSection("types")
+
+ val starsSection = appraiseConfig.configuration.getConfigurationSection("stars")
+ if (starsSection != null) {
+ val stars = mutableMapOf()
+ for (key in starsSection.getKeys(false)) {
+ if (key.toByteOrNull() == null) continue
+ stars[key.toByte()] = starsSection.getInt(key).toByte()
+ }
+ appraiseStars = stars
+ } else {
+ appraiseStars = mapOf()
+ }
+
+ config.save()
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/IntegrationService.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/IntegrationService.kt
new file mode 100644
index 00000000..295a6ff3
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/IntegrationService.kt
@@ -0,0 +1,3 @@
+package io.github.slimefunguguproject.bump.core.services
+
+class IntegrationService
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ListenerService.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ListenerService.kt
new file mode 100644
index 00000000..e5bf54db
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/ListenerService.kt
@@ -0,0 +1,14 @@
+package io.github.slimefunguguproject.bump.core.services
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.implementation.listeners.BowShootListener
+import io.github.slimefunguguproject.bump.implementation.listeners.DragonBreathListener
+import io.github.slimefunguguproject.bump.implementation.listeners.HeavenBreakingSwordListener
+
+class ListenerService(plugin: Bump) {
+ init {
+ BowShootListener(plugin)
+ DragonBreathListener(plugin)
+ HeavenBreakingSwordListener(plugin)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/LocalizationService.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/LocalizationService.kt
new file mode 100644
index 00000000..d50f8749
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/LocalizationService.kt
@@ -0,0 +1,85 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.core.services
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.FileUtils.listYmlFilesInJar
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import net.guizhanss.guizhanlib.minecraft.utils.ItemUtil
+import net.guizhanss.guizhanlib.slimefun.addon.SlimefunLocalization
+import net.guizhanss.guizhanlib.utils.StringUtil
+import net.md_5.bungee.api.ChatMessageType
+import net.md_5.bungee.api.chat.TextComponent
+import org.bukkit.command.CommandSender
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import java.io.File
+import java.text.MessageFormat
+
+class LocalizationService(
+ private val plugin: Bump,
+ private val jarFile: File
+) : SlimefunLocalization(plugin) {
+
+ companion object {
+
+ private const val FOLDER_NAME = "lang"
+ }
+
+ init {
+ extractTranslations()
+ }
+
+ private fun extractTranslations() {
+ val translationsFolder = File(plugin.dataFolder, FOLDER_NAME)
+ if (!translationsFolder.exists()) {
+ translationsFolder.mkdirs()
+ }
+ val translationFiles = listYmlFilesInJar(jarFile, "${FOLDER_NAME}/")
+ for (translationFile in translationFiles) {
+ val filePath = FOLDER_NAME + File.separator + translationFile
+ val file = File(plugin.dataFolder, filePath)
+ if (file.exists()) {
+ continue
+ }
+ plugin.saveResource(filePath, true)
+ }
+ }
+
+ private fun String.toId() = StringUtil.dehumanize(this).uppercase()
+
+ fun getString(key: String, vararg args: Any?): String = MessageFormat.format(getString(key), *args)
+
+ // items
+ fun getItemName(itemId: String, vararg args: Any?) = getString("items.${itemId.toId()}.name", *args)
+ fun getItemLore(itemId: String): List = getStringList("items.${itemId.toId()}.lore")
+
+ // item groups (special items with prefix _IG_)
+ fun getItemGroupName(groupId: String) = getItemName("_IG_${groupId}")
+ fun getItemGroupItem(item: MaterialType, groupId: String) = getItem("_IG_${groupId.toId()}", item.convert())
+
+ // single line lore
+ fun getLore(loreId: String, vararg args: Any?): String = getString("lores.${loreId.lowercase()}", *args)
+
+ // research
+ fun getResearchName(researchId: String): String = getString("researches.${researchId.lowercase()}")
+
+ // gui items (special items with prefix _UI_)
+ fun getGuiItem(item: MaterialType, id: String, vararg extraLore: String): ItemStack =
+ ItemUtil.appendLore(getItem("_UI_${id.toId()}", item.convert()), *extraLore)
+
+ fun getGuiItemName(id: String, vararg args: Any?) = getItemName("_UI_${id.toId()}", *args)
+ fun getGuiItemLore(id: String): List = getItemLore("_UI_${id.toId()}")
+
+ fun sendMessage(sender: CommandSender, key: String, vararg args: Any) {
+ ChatUtil.send(sender, MessageFormat.format(getString("messages.$key"), *args))
+ }
+
+ fun sendActionbarMessage(p: Player, key: String, vararg args: Any) {
+ val message = MessageFormat.format(getString("messages.$key"), *args)
+
+ val components = TextComponent.fromLegacyText(ChatUtil.color(message))
+ p.spigot().sendMessage(ChatMessageType.ACTION_BAR, *components)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.kt
new file mode 100644
index 00000000..64cf72b7
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/BumpSound.kt
@@ -0,0 +1,78 @@
+package io.github.slimefunguguproject.bump.core.services.sounds
+
+import io.github.slimefunguguproject.bump.Bump
+import org.bukkit.Location
+import org.bukkit.Sound
+import org.bukkit.SoundCategory
+import org.bukkit.block.Block
+import org.bukkit.entity.Player
+import java.util.logging.Level
+
+/**
+ * This enum contains almost all configurable sounds in Bump.
+ */
+enum class BumpSound(val sound: Sound, val volume: Float, val pitch: Float) {
+
+ APPRAISER_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0f, 1.0f),
+ APPRAISER_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0f, 1.0f),
+ APPRAISE_TYPE_SELECT(Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f),
+ APPRAISE_TYPE_SELECTOR_OPEN(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1.0f, 1.0f),
+ ATTRIBUTE_GRINDSTONE_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0f, 1.0f),
+ ATTRIBUTE_GRINDSTONE_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0f, 1.0f),
+ QUALITY_IDENTIFIER_OPEN(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1.0f, 1.0f),
+ QUALITY_IDENTIFIER_FAIL(Sound.ENTITY_VILLAGER_NO, 1.0f, 1.0f),
+ QUALITY_IDENTIFIER_SUCCEED(Sound.ENTITY_VILLAGER_CELEBRATE, 1.0f, 1.0f),
+ WITHER_SKULL_BOW_USE(Sound.ENTITY_WITHER_SHOOT, 1.0f, 1.0f),
+ SOUL_SWORD_USE(Sound.AMBIENT_CAVE, 1.0f, 1.0f),
+ HEAVEN_BREAKING_SWORD_USE(Sound.ENTITY_GENERIC_EXPLODE, 1.0f, 1.0f),
+ DEMON_SLAYER_SWORD_USE(Sound.ENTITY_BLAZE_SHOOT, 1.0f, 1.0f),
+ HEAVEN_BREAKING_DEMON_SLAYER_SWORD_USE(Sound.ENTITY_ENDER_DRAGON_SHOOT, 1.0f, 1.0f),
+ ;
+
+ private fun getSoundConfig(): SoundConfig? {
+ val config = Bump.soundService.getSoundConfig(this)
+
+ if (config == null) {
+ Bump.log(Level.WARNING, "Invalid sound config: $name")
+ }
+
+ return config
+ }
+
+ /**
+ * Play this [BumpSound] at [Player]'s eye location.
+ *
+ * @param p The [Player] which to play the [BumpSound] to.
+ */
+ fun playFor(p: Player) {
+ val config = getSoundConfig()
+
+ if (config != null) {
+ p.playSound(p.eyeLocation, config.sound, SoundCategory.PLAYERS, config.volume, config.pitch)
+ }
+ }
+
+ /**
+ * Play this [BumpSound] at the given [Location] using the
+ * provided [SoundCategory].
+ *
+ * @param loc The [Location] at which to play the [BumpSound].
+ * @param category The [SoundCategory] that should be used.
+ */
+ fun playAt(loc: Location, category: SoundCategory) {
+ val config = getSoundConfig()
+
+ if (config != null) {
+ loc.world?.playSound(loc, config.sound, category, config.volume, config.pitch)
+ }
+ }
+
+ /**
+ * Play this [BumpSound] at the given [Block].
+ *
+ * @param block The [Block] at which to play the [BumpSound].
+ */
+ fun playAt(block: Block) {
+ playAt(block.location, SoundCategory.BLOCKS)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.kt
new file mode 100644
index 00000000..5fdbf9b1
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundConfig.kt
@@ -0,0 +1,5 @@
+package io.github.slimefunguguproject.bump.core.services.sounds
+
+import org.bukkit.Sound
+
+internal data class SoundConfig(val sound: Sound, val volume: Float, val pitch: Float)
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.kt
new file mode 100644
index 00000000..5139c19d
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/core/services/sounds/SoundService.kt
@@ -0,0 +1,65 @@
+package io.github.slimefunguguproject.bump.core.services.sounds
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.GeneralUtils.valueOfOrNull
+import net.guizhanss.guizhanlib.slimefun.addon.AddonConfig
+import org.bukkit.Sound
+import java.util.logging.Level
+import kotlin.math.max
+
+class SoundService(private val config: AddonConfig) {
+
+ private val soundMap: MutableMap = mutableMapOf()
+
+ /**
+ * Load the configurations of all [BumpSound].
+ *
+ * @param saveConfig Whether to save config after loading.
+ */
+ fun load(saveConfig: Boolean) {
+ config.reload()
+
+ BumpSound.entries.forEach {
+ try {
+ loadSound(it)
+ } catch (ex: Exception) {
+ Bump.log(Level.SEVERE, ex, "An error occurred while loading sound config for ${it.name}.")
+ }
+ }
+
+ if (saveConfig) {
+ config.save()
+ }
+ }
+
+ /**
+ * Get the [SoundConfig] for a specified [BumpSound].
+ *
+ * @param sound The [BumpSound] to get [SoundConfig] for.
+ *
+ * @return The [SoundConfig] for the [BumpSound]. `null` if not exists.
+ */
+ internal fun getSoundConfig(sound: BumpSound): SoundConfig? {
+ return soundMap[sound]
+ }
+
+ private fun loadSound(sound: BumpSound) {
+ setDefault(sound.name + ".sound", sound.sound.name)
+ setDefault(sound.name + ".volume", sound.volume)
+ setDefault(sound.name + ".pitch", sound.pitch)
+
+ val soundId = config.getString(sound.name + ".sound") ?: sound.sound.name
+ val soundEnum = valueOfOrNull(soundId) ?: sound.sound
+ val volume = max(config.getDouble(sound.name + ".volume"), 0.0)
+ val pitch = max(config.getDouble(sound.name + ".pitch"), 0.5)
+
+ val soundConfig = SoundConfig(soundEnum, volume.toFloat(), pitch.toFloat())
+ soundMap[sound] = soundConfig
+ }
+
+ private fun setDefault(path: String, value: Any) {
+ if (!config.contains(path)) {
+ config[path] = value
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/BumpItems.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/BumpItems.kt
new file mode 100644
index 00000000..1b64d0cc
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/BumpItems.kt
@@ -0,0 +1,589 @@
+package io.github.slimefunguguproject.bump.implementation
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.implementation.groups.BumpItemGroups
+import io.github.slimefunguguproject.bump.implementation.items.RandomEquipment
+import io.github.slimefunguguproject.bump.implementation.items.food.ChewingGum
+import io.github.slimefunguguproject.bump.implementation.items.food.Cola
+import io.github.slimefunguguproject.bump.implementation.items.food.InstantNoodle
+import io.github.slimefunguguproject.bump.implementation.items.food.RiceDumpling
+import io.github.slimefunguguproject.bump.implementation.items.food.SpicyStrips
+import io.github.slimefunguguproject.bump.implementation.items.food.Sprite
+import io.github.slimefunguguproject.bump.implementation.items.machines.Appraiser
+import io.github.slimefunguguproject.bump.implementation.items.machines.AttributeGrindstone
+import io.github.slimefunguguproject.bump.implementation.items.machines.ItemConverter
+import io.github.slimefunguguproject.bump.implementation.items.materials.BumpMaterial
+import io.github.slimefunguguproject.bump.implementation.items.tools.GetGoldSpade
+import io.github.slimefunguguproject.bump.implementation.items.tools.QualityIdentifier
+import io.github.slimefunguguproject.bump.implementation.items.weapons.DemonSlayerSword
+import io.github.slimefunguguproject.bump.implementation.items.weapons.HeavenBreakingDemonSlayerSword
+import io.github.slimefunguguproject.bump.implementation.items.weapons.HeavenBreakingSword
+import io.github.slimefunguguproject.bump.implementation.items.weapons.LightningBow
+import io.github.slimefunguguproject.bump.implementation.items.weapons.NormalSword
+import io.github.slimefunguguproject.bump.implementation.items.weapons.SoulSword
+import io.github.slimefunguguproject.bump.implementation.items.weapons.WitherSkullBow
+import io.github.slimefunguguproject.bump.implementation.recipes.BumpRecipeTypes
+import io.github.slimefunguguproject.bump.utils.GeneralUtils
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.RecipeUtils
+import io.github.slimefunguguproject.bump.utils.items.buildSlimefunItem
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack
+import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.EnchantmentX
+import org.bukkit.Material
+import org.bukkit.enchantments.Enchantment
+import org.bukkit.inventory.ItemStack
+
+
+object BumpItems {
+
+ //
+ val PHOTOSYNTHETIC_ENERGY = buildSlimefunItem {
+ id = "PHOTOSYNTHETIC_ENERGY"
+ material = MaterialType.Material(Material.BELL)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.MAGIC_WORKBENCH
+ recipe = arrayOf(
+ ItemStack(Material.CHORUS_FLOWER), ItemStack(Material.SUNFLOWER), ItemStack(Material.CHORUS_FLOWER),
+ null, null, null,
+ null, null, null
+ )
+ }
+
+ val MECHANICAL_GEAR = buildSlimefunItem {
+ id = "MECHANICAL_GEAR"
+ material = MaterialType.Material(Material.ENDER_PEARL)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
+ null, SlimefunItems.COPPER_WIRE, null,
+ SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
+ // @formatter:on
+ )
+ }
+
+ val BROKEN_GOLD_COIN = buildSlimefunItem {
+ id = "BROKEN_GOLD_COIN"
+ material = MaterialType.Material(Material.GOLD_NUGGET)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = BumpRecipeTypes.GET_GOLD_SPADE
+ recipe = RecipeUtils.centerRecipe(ItemStack(Material.SAND))
+ }
+
+ val COMPUTER_TECH_CORE = buildSlimefunItem {
+ id = "COMPUTER_TECH_CORE"
+ material = MaterialType.Material(Material.DIAMOND)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.BATTERY, SlimefunItems.BATTERY, SlimefunItems.BATTERY,
+ SlimefunItems.COOLING_UNIT, SlimefunItems.POWER_CRYSTAL, SlimefunItems.COOLING_UNIT,
+ SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
+ // @formatter:on
+ )
+ }
+
+ val BROKEN_CPU = buildSlimefunItem {
+ id = "BROKEN_CPU"
+ material = MaterialType.Material(Material.PRISMARINE_CRYSTALS)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE,
+ SlimefunItems.COPPER_WIRE, COMPUTER_TECH_CORE, SlimefunItems.COPPER_WIRE,
+ SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE,
+ // @formatter:on
+ )
+ }
+
+ val CPU = buildSlimefunItem {
+ id = "CPU"
+ material = MaterialType.Material(Material.DIAMOND)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.COMPRESSOR
+ recipe = arrayOf(BROKEN_CPU)
+ }
+
+ val ANCIENT_RUNE_SOUL = buildSlimefunItem {
+ id = "ANCIENT_RUNE_SOUL"
+ material = MaterialType.Material(Material.PAPER)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ANCIENT_ALTAR
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.MAGIC_LUMP_1, SlimefunItems.ESSENCE_OF_AFTERLIFE, SlimefunItems.MAGIC_LUMP_1,
+ SlimefunItems.SOULBOUND_RUNE, SlimefunItems.SOULBOUND_RUNE, SlimefunItems.SOULBOUND_RUNE,
+ SlimefunItems.MAGIC_LUMP_1, SlimefunItems.ESSENCE_OF_AFTERLIFE, SlimefunItems.MAGIC_LUMP_1,
+ // @formatter:on
+ )
+ }
+
+ val INSTANT_NOODLE_SEASONING = buildSlimefunItem {
+ id = "INSTANT_NOODLE_SEASONING"
+ material = MaterialType.Material(Material.BEETROOT_SEEDS)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.SALT, SlimefunItems.SALT, SlimefunItems.SALT,
+ SlimefunItems.CARROT_FERTILIZER, SlimefunItems.CARROT_FERTILIZER, SlimefunItems.CARROT_FERTILIZER,
+ SlimefunItems.SALT, SlimefunItems.SALT, SlimefunItems.SALT,
+ // @formatter:on
+ )
+ }
+
+ val POP_CANDY = buildSlimefunItem {
+ id = "POP_CANDY"
+ material = MaterialType.Material(Material.SUGAR)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.PRESSURE_CHAMBER
+ recipe = arrayOf(SlimefunItems.MAGIC_SUGAR)
+ }
+
+ val PEACH_WOOD = buildSlimefunItem {
+ id = "PEACH_WOOD"
+ material = MaterialType.Material(Material.STICK)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ ItemStack(Material.ACACIA_WOOD), ItemStack(Material.BIRCH_WOOD), ItemStack(Material.DARK_OAK_WOOD),
+ null, null, null,
+ null, null, null
+ )
+ }
+
+ val UPDATE_CORE = buildSlimefunItem {
+ id = "UPDATE_CORE"
+ material = MaterialType.Material(Material.ZOMBIE_HEAD)
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.POWER_CRYSTAL, SlimefunItems.LAVA_CRYSTAL, SlimefunItems.POWER_CRYSTAL,
+ SlimefunItems.LAVA_CRYSTAL, CPU, SlimefunItems.LAVA_CRYSTAL,
+ SlimefunItems.GOLD_24K, SlimefunItems.GOLD_24K, SlimefunItems.GOLD_24K,
+ // @formatter:on
+ )
+ }
+
+ val COMPRESSED_RANDOM_EQUIPMENT = buildSlimefunItem {
+ id = "COMPRESSED_RANDOM_EQUIPMENT"
+ material = MaterialType.Head("bb82d5e2033ce8d9821d53e59d480f3dd60b4f9e555f67056c938c0240e16ffe")
+ itemGroup = BumpItemGroups.MATERIALS
+ recipeType = RecipeType.COMPRESSOR
+ recipe = RecipeUtils.centerRecipe(
+ CustomItemStack(Material.DIAMOND_CHESTPLATE, Bump.localization.getLore("any-random-equipment"))
+ )
+ }
+ //
+
+ //
+ val SPRITE = buildSlimefunItem {
+ id = "SPRITE"
+ material = MaterialType.Material(Material.POTION)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.MAGIC_WORKBENCH
+ recipe = arrayOf(
+ // @formatter:off
+ POP_CANDY, ItemStack(Material.WATER_BUCKET), POP_CANDY,
+ ItemStack(Material.WATER_BUCKET), POP_CANDY, ItemStack(Material.WATER_BUCKET),
+ POP_CANDY, ItemStack(Material.WATER_BUCKET), POP_CANDY,
+ // @formatter:on
+ )
+ postCreate = {
+ GeneralUtils.glowItem(it)
+ }
+ }
+
+ val COLA = buildSlimefunItem {
+ id = "COLA"
+ material = MaterialType.Material(Material.POTION)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.MAGIC_WORKBENCH
+ recipe = arrayOf(
+ // @formatter:off
+ POP_CANDY, ItemStack(Material.WATER_BUCKET), POP_CANDY,
+ ItemStack(Material.WATER_BUCKET), SlimefunItems.MAGIC_SUGAR, ItemStack(Material.WATER_BUCKET),
+ POP_CANDY, ItemStack(Material.WATER_BUCKET), POP_CANDY,
+ // @formatter:on
+ )
+ }
+
+ val INSTANT_NOODLE = buildSlimefunItem {
+ id = "INSTANT_NOODLE"
+ material = MaterialType.Material(Material.STRING)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.MAGIC_WORKBENCH
+ recipe = arrayOf(
+ // @formatter:off
+ ItemStack(Material.WATER_BUCKET), ItemStack(Material.WATER_BUCKET), ItemStack(Material.WATER_BUCKET),
+ INSTANT_NOODLE_SEASONING, INSTANT_NOODLE_SEASONING, INSTANT_NOODLE_SEASONING,
+ SlimefunItems.WHEAT_FLOUR, SlimefunItems.WHEAT_FLOUR, SlimefunItems.WHEAT_FLOUR,
+ // @formatter:on
+ )
+ }
+
+ val SPICY_STRIPS = buildSlimefunItem {
+ id = "SPICY_STRIPS"
+ material = MaterialType.Material(Material.ROTTEN_FLESH)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.COMPRESSOR
+ recipe = arrayOf(SlimefunItems.WHEAT_FLOUR)
+ }
+
+ val CHEWING_GUM = buildSlimefunItem {
+ id = "CHEWING_GUM"
+ material = MaterialType.Material(Material.SUGAR)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.COMPRESSOR
+ recipe = arrayOf(SlimefunItems.MAGIC_SUGAR)
+ }
+
+ val RICE_DUMPLING = buildSlimefunItem {
+ id = "RICE_DUMPLING"
+ material = MaterialType.Material(Material.GREEN_DYE)
+ itemGroup = BumpItemGroups.FOOD
+ recipeType = RecipeType.MAGIC_WORKBENCH
+ recipe = arrayOf(
+ ItemStack(Material.LILY_PAD), ItemStack(Material.ACACIA_LEAVES), ItemStack(Material.LILY_PAD),
+ ItemStack(Material.ACACIA_LEAVES), ItemStack(Material.WHEAT), ItemStack(Material.ACACIA_LEAVES),
+ ItemStack(Material.LILY_PAD), ItemStack(Material.ACACIA_LEAVES), ItemStack(Material.LILY_PAD),
+ )
+ }
+ //
+
+ //
+ val GET_GOLD_SPADE = buildSlimefunItem {
+ id = "GET_GOLD_SPADE"
+ material = MaterialType.Material(Material.GOLDEN_SHOVEL)
+ itemGroup = BumpItemGroups.TOOLS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, SlimefunItems.GOLD_24K, null,
+ null, ItemStack(Material.STICK), null,
+ null, ItemStack(Material.STICK), null,
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(Enchantment.MENDING, 1)
+ }
+ }
+
+ val QUALITY_IDENTIFIER = buildSlimefunItem {
+ id = "QUALITY_IDENTIFIER"
+ material = MaterialType.Material(Material.PAPER)
+ itemGroup = BumpItemGroups.TOOLS
+ recipeType = RecipeType.SMELTERY
+ recipe = arrayOf(COMPRESSED_RANDOM_EQUIPMENT)
+
+ +LoreBuilder.usesLeft(QualityIdentifier.MAX_USES)
+ }
+ //
+
+ //
+ val APPRAISER = buildSlimefunItem {
+ id = "APPRAISER"
+ material = MaterialType.Material(Material.BELL)
+ itemGroup = BumpItemGroups.MACHINES
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ SlimefunItems.BATTERY, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.BATTERY,
+ MECHANICAL_GEAR, CPU, MECHANICAL_GEAR,
+ SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.COOLING_UNIT, SlimefunItems.ADVANCED_CIRCUIT_BOARD,
+ // @formatter:off
+ )
+
+ +LoreBuilder.power(Appraiser.ENERGY_CONSUMPTION, " ${Bump.localization.getLore("per-use")}")
+ }
+
+ val ATTRIBUTE_GRINDSTONE = buildSlimefunItem {
+ id = "ATTRIBUTE_GRINDSTONE"
+ material = MaterialType.Material(Material.GRINDSTONE)
+ itemGroup = BumpItemGroups.MACHINES
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ SlimefunItems.ELECTRO_MAGNET, APPRAISER, SlimefunItems.ELECTRO_MAGNET,
+ MECHANICAL_GEAR, CPU, MECHANICAL_GEAR,
+ UPDATE_CORE, null, UPDATE_CORE,
+ )
+
+ +LoreBuilder.power(AttributeGrindstone.ENERGY_CONSUMPTION, " ${Bump.localization.getLore("per-use")}")
+ }
+
+ val ITEM_CONVERTER = buildSlimefunItem {
+ id = "ITEM_CONVERTER"
+ material = MaterialType.Material(Material.CRAFTING_TABLE)
+ itemGroup = BumpItemGroups.MACHINES
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ null, ItemStack(Material.REDSTONE), null,
+ ItemStack(Material.DIAMOND), ItemStack(Material.SMITHING_TABLE), ItemStack(Material.DIAMOND),
+ null, ItemStack(Material.REDSTONE_BLOCK), null,
+ // @formatter:on
+ )
+ }
+ //
+
+ //
+ val RANDOM_HELMET = buildSlimefunItem {
+ id = "RANDOM_HELMET"
+ material = MaterialType.Material(Material.DIAMOND_HELMET)
+ itemGroup = BumpItemGroups.ARMOR
+ recipeType = RecipeType.ARMOR_FORGE
+ recipe = arrayOf(
+ ItemStack(Material.DIAMOND), ItemStack(Material.DIAMOND), ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), UPDATE_CORE, ItemStack(Material.DIAMOND),
+ BROKEN_GOLD_COIN, null, BROKEN_GOLD_COIN,
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+
+ val RANDOM_CHESTPLATE = buildSlimefunItem {
+ id = "RANDOM_CHESTPLATE"
+ material = MaterialType.Material(Material.DIAMOND_CHESTPLATE)
+ itemGroup = BumpItemGroups.ARMOR
+ recipeType = RecipeType.ARMOR_FORGE
+ recipe = arrayOf(
+ ItemStack(Material.DIAMOND), BROKEN_GOLD_COIN, ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), UPDATE_CORE, ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), ItemStack(Material.DIAMOND), ItemStack(Material.DIAMOND),
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+
+ val RANDOM_LEGGINGS = buildSlimefunItem {
+ id = "RANDOM_LEGGINGS"
+ material = MaterialType.Material(Material.DIAMOND_LEGGINGS)
+ itemGroup = BumpItemGroups.ARMOR
+ recipeType = RecipeType.ARMOR_FORGE
+ recipe = arrayOf(
+ ItemStack(Material.DIAMOND), BROKEN_GOLD_COIN, ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), UPDATE_CORE, ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), null, ItemStack(Material.DIAMOND),
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+
+ val RANDOM_BOOTS = buildSlimefunItem {
+ id = "RANDOM_BOOTS"
+ material = MaterialType.Material(Material.DIAMOND_BOOTS)
+ itemGroup = BumpItemGroups.ARMOR
+ recipeType = RecipeType.ARMOR_FORGE
+ recipe = arrayOf(
+ null, null, null,
+ ItemStack(Material.DIAMOND), UPDATE_CORE, ItemStack(Material.DIAMOND),
+ ItemStack(Material.DIAMOND), BROKEN_GOLD_COIN, ItemStack(Material.DIAMOND)
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+
+ val RANDOM_HORSE_ARMOR = buildSlimefunItem {
+ id = "RANDOM_HORSE_ARMOR"
+ material = MaterialType.Material(Material.DIAMOND_HORSE_ARMOR)
+ itemGroup = BumpItemGroups.ARMOR
+ recipeType = RecipeType.ARMOR_FORGE
+ recipe = arrayOf(
+ null, BROKEN_GOLD_COIN, null,
+ null, ItemStack(Material.DIAMOND_HORSE_ARMOR), null,
+ null, UPDATE_CORE, null,
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+ //
+
+ //
+ val RANDOM_SWORD = buildSlimefunItem {
+ id = "RANDOM_SWORD"
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, UPDATE_CORE, null,
+ null, COMPUTER_TECH_CORE, null,
+ null, ItemStack(Material.STICK), null
+ )
+ postCreate = {
+ AppraiseUtils.setAppraisable(it)
+ }
+ }
+
+ val LIGHTNING_BOW = buildSlimefunItem(10) {
+ id = "LIGHTNING_BOW"
+ material = MaterialType.Material(Material.BOW)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ // @formatter:off
+ null, SlimefunItems.STAFF_STORM, SlimefunItems.LIGHTNING_RUNE,
+ SlimefunItems.POWER_CRYSTAL, SlimefunItems.LIGHTNING_RUNE, SlimefunItems.STAFF_STORM,
+ null, SlimefunItems.STAFF_STORM, SlimefunItems.LIGHTNING_RUNE,
+ // @formatter:on
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.POWER, 5)
+ }
+ }
+
+ val WITHER_SKULL_BOW = buildSlimefunItem(5) {
+ id = "WITHER_SKULL_BOW"
+ material = MaterialType.Material(Material.BOW)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, PEACH_WOOD, SlimefunItems.NECROTIC_SKULL,
+ PEACH_WOOD, SlimefunItems.POWER_CRYSTAL, SlimefunItems.NECROTIC_SKULL,
+ null, PEACH_WOOD, SlimefunItems.NECROTIC_SKULL,
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.POWER, 5)
+ }
+ }
+
+ val EMERALD_SWORD = buildSlimefunItem {
+ id = "EMERALD_SWORD"
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, ItemStack(Material.EMERALD), null,
+ null, ItemStack(Material.EMERALD), null,
+ null, ItemStack(Material.STICK), null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 2)
+ }
+ }
+
+ val BONE_SWORD = buildSlimefunItem {
+ id = "BONE_SWORD"
+ material = MaterialType.Material(Material.WOODEN_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, ItemStack(Material.BONE_BLOCK, 64), null,
+ null, ItemStack(Material.BONE_BLOCK, 64), null,
+ null, SlimefunItems.GRANDMAS_WALKING_STICK, null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 10)
+ }
+ }
+
+ val GUARDIAN_SWORD = buildSlimefunItem {
+ id = "GUARDIAN_SWORD"
+ material = MaterialType.Material(Material.GOLDEN_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, PHOTOSYNTHETIC_ENERGY, null,
+ null, PHOTOSYNTHETIC_ENERGY, null,
+ null, ItemStack(Material.STICK), null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 5)
+ it.addUnsafeEnchantment(Enchantment.MENDING, 1)
+ }
+ }
+
+ val PEACH_WOOD_SWORD = buildSlimefunItem {
+ id = "PEACH_WOOD_SWORD"
+ material = MaterialType.Material(Material.WOODEN_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, PEACH_WOOD, null,
+ null, PEACH_WOOD, null,
+ null, ItemStack(Material.STICK), null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(Enchantment.KNOCKBACK, 5)
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 3)
+ }
+ }
+
+ val SOUL_SWORD = buildSlimefunItem {
+ id = "SOUL_SWORD"
+ material = MaterialType.Material(Material.IRON_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, null, null,
+ ANCIENT_RUNE_SOUL, ItemStack(Material.DIAMOND_SWORD), ANCIENT_RUNE_SOUL,
+ null, null, null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 2)
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 1)
+ }
+ }
+
+ val HEAVEN_BREAKING_SWORD = buildSlimefunItem(5) {
+ id = "HEAVEN_BREAKING_SWORD"
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ SlimefunItems.MAGIC_LUMP_2, SlimefunItems.AIR_RUNE, SlimefunItems.MAGIC_LUMP_2,
+ SlimefunItems.RAINBOW_RUNE, SlimefunItems.RAINBOW_RUNE, SlimefunItems.MAGIC_LUMP_2,
+ SlimefunItems.AIR_RUNE, SlimefunItems.MAGIC_LUMP_2, null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 1)
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 1)
+ it.addUnsafeEnchantment(Enchantment.SWEEPING_EDGE, 1)
+ }
+ }
+
+ val DEMON_SLAYER_SWORD = buildSlimefunItem(5) {
+ id = "DEMON_SLAYER_SWORD"
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ SlimefunItems.MAGIC_LUMP_2, SlimefunItems.ENDER_RUNE, SlimefunItems.MAGIC_LUMP_2,
+ SlimefunItems.FIRE_RUNE, SlimefunItems.FIRE_RUNE, SlimefunItems.MAGIC_LUMP_2,
+ SlimefunItems.ENDER_RUNE, SlimefunItems.MAGIC_LUMP_2, null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 1)
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 1)
+ it.addUnsafeEnchantment(Enchantment.SWEEPING_EDGE, 1)
+ }
+ }
+
+ val HEAVEN_BREAKING_DEMON_SLAYER_SWORD = buildSlimefunItem(5) {
+ id = "HEAVEN_BREAKING_DEMON_SLAYER_SWORD"
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ itemGroup = BumpItemGroups.WEAPONS
+ recipeType = RecipeType.ENHANCED_CRAFTING_TABLE
+ recipe = arrayOf(
+ null, null, null,
+ HEAVEN_BREAKING_SWORD, UPDATE_CORE, DEMON_SLAYER_SWORD,
+ null, null, null
+ )
+ postCreate = {
+ it.addUnsafeEnchantment(EnchantmentX.SHARPNESS, 5)
+ it.addUnsafeEnchantment(EnchantmentX.UNBREAKING, 5)
+ it.addUnsafeEnchantment(Enchantment.LOYALTY, 5)
+ }
+ }
+ //
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.kt
new file mode 100644
index 00000000..c5c1ef60
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoGroup.kt
@@ -0,0 +1,30 @@
+package io.github.slimefunguguproject.bump.implementation.groups
+
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.implementation.menu.AppraiseTypeMenu
+import io.github.thebusybiscuit.slimefun4.api.items.groups.FlexItemGroup
+import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile
+import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide
+import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode
+import org.bukkit.NamespacedKey
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+
+class AppraiseInfoGroup(
+ private val name: String,
+ key: NamespacedKey,
+ item: ItemStack
+) : FlexItemGroup(key, item) {
+
+ override fun isVisible(player: Player, playerProfile: PlayerProfile, guideMode: SlimefunGuideMode) = false
+
+ override fun open(p: Player, profile: PlayerProfile, mode: SlimefunGuideMode) {
+ AppraiseInfoMenu(name, { type: AppraiseType ->
+ // open the detail menu
+ AppraiseTypeMenu(type) { open(p, profile, mode) }.open(p)
+ }, {
+ // back to main menu
+ SlimefunGuide.openItemGroup(profile, BumpItemGroups.MAIN, mode, 1)
+ }).open(p)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.kt
new file mode 100644
index 00000000..e1972997
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/AppraiseInfoMenu.kt
@@ -0,0 +1,18 @@
+package io.github.slimefunguguproject.bump.implementation.groups
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.implementation.menu.AppraiseTypesMenu
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import org.bukkit.Material
+import java.util.function.Consumer
+
+internal class AppraiseInfoMenu(
+ name: String,
+ successCallback: Consumer,
+ backCallback: Runnable
+) : AppraiseTypesMenu(name, successCallback, backCallback) {
+
+ override fun getInfoItem() =
+ Bump.localization.getGuiItem(MaterialType.Material(Material.NAME_TAG), "APPRAISE_MENU_INFO")
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.kt
new file mode 100644
index 00000000..14fceb39
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/groups/BumpItemGroups.kt
@@ -0,0 +1,139 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.groups
+
+import dev.sefiraat.sefilib.slimefun.itemgroup.DummyItemGroup
+import dev.sefiraat.sefilib.slimefun.itemgroup.MenuItem
+import dev.sefiraat.sefilib.slimefun.itemgroup.SimpleFlexGroup
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.constant.Keys.createKey
+import io.github.slimefunguguproject.bump.utils.constant.Strings
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack
+import org.bukkit.ChatColor
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+
+object BumpItemGroups {
+
+ val MAIN: SimpleFlexGroup = SimpleFlexGroup(
+ Bump.instance,
+ Bump.localization.getItemGroupName("main"),
+ "main".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.DIAMOND),
+ "main"
+ )
+ )
+
+ val WIKI: ItemStack = Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.KNOWLEDGE_BOOK),
+ "wiki"
+ )
+
+ val MATERIALS: ItemGroup = DummyItemGroup(
+ "materials".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.NETHER_STAR),
+ "materials"
+ )
+ )
+
+ val FOOD: ItemGroup = DummyItemGroup(
+ "food".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.BREAD),
+ "food"
+ )
+ )
+
+ val TOOLS: ItemGroup = DummyItemGroup(
+ "tools".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.DIAMOND_PICKAXE),
+ "tools"
+ )
+ )
+
+ val MACHINES: ItemGroup = DummyItemGroup(
+ "machines".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.ANVIL),
+ "machines"
+ )
+ )
+
+ val ARMOR: ItemGroup = DummyItemGroup(
+ "armor".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.DIAMOND_HELMET),
+ "armor"
+ )
+ )
+
+ val WEAPONS: ItemGroup = DummyItemGroup(
+ "weapons".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.DIAMOND_SWORD),
+ "weapons"
+ )
+ )
+
+ val APPRAISE_INFO: AppraiseInfoGroup = AppraiseInfoGroup(
+ Bump.localization.getItemGroupName("appraise_info"),
+ "appraise_info".createKey(),
+ Bump.localization.getItemGroupItem(
+ MaterialType.Material(Material.NAME_TAG),
+ "appraise_info"
+ )
+ )
+
+ val HIDDEN: ItemGroup = DummyItemGroup(
+ "hidden".createKey(),
+ CustomItemStack(
+ Material.BARRIER,
+ "&bBump - Hidden/Legacy Items"
+ )
+ )
+
+ fun setup() {
+ val addon = Bump.instance
+ val wikiMenuItem = MenuItem(WIKI) { p: Player, _, _, _ ->
+ p.closeInventory()
+ p.sendMessage("")
+ Bump.localization.sendMessage(p, "click-here")
+
+ val lang = Bump.configService.lang
+ if (lang.startsWith("zh")) {
+ p.sendMessage(ChatColor.GRAY.toString() + Strings.WIKI_CN)
+ } else {
+ p.sendMessage(ChatColor.GRAY.toString() + Strings.WIKI_EN)
+ }
+
+ p.sendMessage("")
+ false
+ }
+
+ MAIN.addMenuItem(wikiMenuItem)
+ MAIN.addItemGroup(MATERIALS)
+ MAIN.addItemGroup(FOOD)
+ MAIN.addItemGroup(TOOLS)
+ MAIN.addItemGroup(MACHINES)
+ MAIN.addItemGroup(ARMOR)
+ MAIN.addItemGroup(WEAPONS)
+ MAIN.addItemGroup(APPRAISE_INFO)
+
+ MAIN.register(addon)
+
+ MATERIALS.register(addon)
+ FOOD.register(addon)
+ MACHINES.register(addon)
+ TOOLS.register(addon)
+ ARMOR.register(addon)
+ WEAPONS.register(addon)
+ APPRAISE_INFO.register(addon)
+ HIDDEN.register(addon)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.kt
new file mode 100644
index 00000000..fbb7e6a8
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/RandomEquipment.kt
@@ -0,0 +1,24 @@
+package io.github.slimefunguguproject.bump.implementation.items
+
+import io.github.slimefunguguproject.bump.core.attributes.AppraisableItem
+import io.github.slimefunguguproject.bump.implementation.BumpItems
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Compressor
+import org.bukkit.inventory.ItemStack
+
+class RandomEquipment(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+) : SlimefunItem(itemGroup, itemStack, recipeType, recipe), AppraisableItem {
+
+ override fun postRegister() {
+ if (isDisabled) return
+ val compressor: Compressor = (getById("COMPRESSOR") ?: return) as Compressor
+ compressor.addRecipe(arrayOf(item), BumpItems.COMPRESSED_RANDOM_EQUIPMENT)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ChewingGum.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ChewingGum.kt
new file mode 100644
index 00000000..c688684d
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ChewingGum.kt
@@ -0,0 +1,25 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.PotionEffectTypeX
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+
+
+class ChewingGum(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ItemFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.add(p, 10)
+ p.addPotionEffect(PotionEffect(PotionEffectTypeX.SLOWNESS, 600, 4))
+ p.addPotionEffect(PotionEffect(PotionEffectTypeX.RESISTANCE, 600, 4))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Cola.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Cola.kt
new file mode 100644
index 00000000..d8e2c207
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Cola.kt
@@ -0,0 +1,24 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+
+
+class Cola(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ConsumableFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.add(p, 6)
+ p.addPotionEffect(PotionEffect(PotionEffectType.LEVITATION, 600, 3))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.kt
new file mode 100644
index 00000000..fbaeed80
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ConsumableFood.kt
@@ -0,0 +1,34 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.ItemUtils
+import org.bukkit.GameMode
+import org.bukkit.entity.Player
+import org.bukkit.event.player.PlayerItemConsumeEvent
+import org.bukkit.inventory.ItemStack
+
+
+abstract class ConsumableFood(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : SimpleSlimefunItem(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun getItemHandler() = ItemConsumptionHandler { e: PlayerItemConsumeEvent, p: Player, _: ItemStack ->
+ val messageKey = id.replace(Bump.localization.idPrefix, "").lowercase()
+ Bump.localization.sendActionbarMessage(p, "food.$messageKey")
+
+ if (p.gameMode != GameMode.CREATIVE) {
+ ItemUtils.consumeItem(e.item, false)
+ }
+ applyFoodEffects(p)
+ }
+
+ abstract fun applyFoodEffects(p: Player)
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/InstantNoodle.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/InstantNoodle.kt
new file mode 100644
index 00000000..ef109fc3
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/InstantNoodle.kt
@@ -0,0 +1,25 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+
+
+class InstantNoodle(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ItemFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.set(p, 20)
+ p.addPotionEffect(PotionEffect(PotionEffectType.HEALTH_BOOST, 1500, 9))
+ p.addPotionEffect(PotionEffect(PotionEffectType.REGENERATION, 200, 4))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.kt
new file mode 100644
index 00000000..6b1de712
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/ItemFood.kt
@@ -0,0 +1,63 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.ItemUtils
+import net.guizhanss.guizhanlib.common.Cooldown
+import org.bukkit.GameMode
+import org.bukkit.Sound
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.scheduler.BukkitRunnable
+import java.util.UUID
+
+
+abstract class ItemFood(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : UnplaceableBlock(itemGroup, itemStack, recipeType, recipe) {
+
+ private val cooldown = Cooldown()
+
+ override fun getItemHandler() = ItemUseHandler { e: PlayerRightClickEvent ->
+ e.cancel()
+ val p = e.player
+
+ if (!cooldown.check(p.uniqueId)) {
+ Bump.localization.sendActionbarMessage(p, "food.cooldown")
+ return@ItemUseHandler
+ }
+
+ val messageKey = id.replace(Bump.localization.idPrefix, "").lowercase()
+ Bump.localization.sendActionbarMessage(p, "food.$messageKey")
+
+ if (p.gameMode != GameMode.CREATIVE) {
+ ItemUtils.consumeItem(e.item, false)
+ }
+
+ object : BukkitRunnable() {
+ var count = 7
+
+ override fun run() {
+ if (count > 0) {
+ p.playSound(p.location, Sound.ENTITY_GENERIC_EAT, 1f, 1f)
+ count--
+ } else {
+ applyFoodEffects(p)
+ cancel()
+ }
+ }
+ }.runTaskTimer(Bump.instance, 1L, 4L)
+
+ cooldown[p.uniqueId] = 2000L
+ }
+
+ abstract fun applyFoodEffects(p: Player)
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/RiceDumpling.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/RiceDumpling.kt
new file mode 100644
index 00000000..1755a53f
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/RiceDumpling.kt
@@ -0,0 +1,29 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.PotionEffectTypeX
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+
+
+class RiceDumpling(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ItemFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.add(p, 8)
+ p.addPotionEffect(PotionEffect(PotionEffectType.CONDUIT_POWER, 200, 1))
+ p.addPotionEffect(PotionEffect(PotionEffectType.GLOWING, 1000, 1))
+ p.addPotionEffect(PotionEffect(PotionEffectTypeX.STRENGTH, 200, 1))
+ p.addPotionEffect(PotionEffect(PotionEffectTypeX.HASTE, 200, 2))
+ p.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 2000, 2))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/SpicyStrips.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/SpicyStrips.kt
new file mode 100644
index 00000000..c4a9fac6
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/SpicyStrips.kt
@@ -0,0 +1,31 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+
+
+class SpicyStrips(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ConsumableFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.add(p, 2)
+ p.addPotionEffect(PotionEffect(PotionEffectType.ABSORPTION, 200, 2))
+
+ Bump.scheduler().run {
+ if (p.hasPotionEffect(PotionEffectType.HUNGER)) {
+ p.removePotionEffect(PotionEffectType.HUNGER)
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Sprite.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Sprite.kt
new file mode 100644
index 00000000..73d4e522
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/food/Sprite.kt
@@ -0,0 +1,24 @@
+package io.github.slimefunguguproject.bump.implementation.items.food
+
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+
+
+class Sprite(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : ConsumableFood(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun applyFoodEffects(p: Player) {
+ FoodLevelUtils.add(p, 6)
+ p.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 2000, 4))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/Appraiser.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/Appraiser.kt
new file mode 100644
index 00000000..fbdb22c5
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/Appraiser.kt
@@ -0,0 +1,178 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.items.machines
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.implementation.items.RandomEquipment
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils
+import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction
+import me.mrCookieSlime.Slimefun.api.BlockStorage
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu
+import org.bukkit.Location
+import org.bukkit.Material
+import org.bukkit.NamespacedKey
+import org.bukkit.block.Block
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import java.util.logging.Level
+
+class Appraiser(
+ itemGroup: ItemGroup,
+ item: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : SimpleMenuBlock(itemGroup, item, recipeType, recipe) {
+
+ companion object {
+
+ // energy
+ const val ENERGY_CONSUMPTION = 114514
+
+ private const val APPRAISE_TYPE_SLOT = 4
+ private const val APPRAISE_TYPE_KEY = "appraise_type"
+ }
+
+ override val operationSlotItem = Bump.localization.getGuiItem(
+ MaterialType.Material(Material.NAME_TAG),
+ "APPRAISER_USE",
+ )
+
+ override fun getCapacity() = ENERGY_CONSUMPTION
+
+ override fun onNewInstance(menu: BlockMenu, b: Block) {
+ super.onNewInstance(menu, b)
+ updateSelector(menu, b.location)
+ }
+
+ override fun onOperate(menu: BlockMenu, b: Block, p: Player, action: ClickAction) {
+ appraise(menu, p)
+ }
+
+ override fun register(addon: SlimefunAddon) {
+ if (BumpRegistry.appraiseTypes.isEmpty()) {
+ Bump.log(Level.WARNING, "No appraise types registered, Appraiser will not be registered.")
+ return
+ }
+ super.register(addon)
+ }
+
+ private fun openSelector(p: Player, menu: BlockMenu, l: Location) {
+ AppraiserSelector({ type: AppraiseType ->
+ BlockStorage.addBlockInfo(l, APPRAISE_TYPE_KEY, type.key.toString())
+ updateSelector(menu, l)
+ BumpSound.APPRAISE_TYPE_SELECT.playFor(p)
+ menu.open(p)
+ }, {
+ menu.open(p)
+ }).open(p)
+ }
+
+ private fun appraise(menu: BlockMenu, p: Player) {
+ val item = menu.getItemInSlot(INPUT_SLOT)
+
+ // null check
+ if (!ValidateUtils.noAirItem(item)) {
+ Bump.localization.sendMessage(p, "no-input")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ // validate input
+ if (!validate(item)) {
+ Bump.localization.sendMessage(p, "machine.appraiser.invalid")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ // check if input item is already appraised
+ if (AppraiseUtils.isAppraised(item)) {
+ Bump.localization.sendMessage(p, "machine.appraiser.appraised")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ // check output slot
+ if (menu.getItemInSlot(OUTPUT_SLOT) != null) {
+ Bump.localization.sendMessage(p, "output-no-space")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ // check energy
+ val charge: Int = getCharge(menu.location)
+ if (charge < ENERGY_CONSUMPTION) {
+ Bump.localization.sendMessage(p, "not-enough-power")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ // Check current appraise type
+ val type: AppraiseType = getCurrentType(menu.location)
+ if (!type.hasPermission(p)) {
+ Bump.localization.sendMessage(p, "no-permission")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+ if (!type.isValidItem(item)) {
+ Bump.localization.sendMessage(p, "machine.appraiser.not-accepted")
+ BumpSound.APPRAISER_FAIL.playFor(p)
+ return
+ }
+
+ val output = item.clone()
+ val result = type.appraise()
+
+ result.apply(output)
+
+ menu.replaceExistingItem(INPUT_SLOT, null)
+ menu.pushItem(output, OUTPUT_SLOT)
+
+ setCharge(menu.location, 0)
+ Bump.localization.sendMessage(p, "machine.appraiser.success")
+ BumpSound.APPRAISER_SUCCEED.playFor(p)
+ }
+
+ private fun validate(itemStack: ItemStack) =
+ getByItem(itemStack) is RandomEquipment || AppraiseUtils.isAppraisable(itemStack)
+
+ private fun updateSelector(menu: BlockMenu, l: Location) {
+ val type: AppraiseType = getCurrentType(l)
+ menu.replaceExistingItem(
+ APPRAISE_TYPE_SLOT, Bump.localization.getGuiItem(
+ MaterialType.Material(Material.PAPER),
+ "APPRAISER_SELECTOR",
+ type.name,
+ *type.description.toTypedArray()
+ )
+ )
+ menu.addMenuClickHandler(APPRAISE_TYPE_SLOT) { player: Player, _, _, _ ->
+ openSelector(player, menu, l)
+ false
+ }
+ }
+
+ private fun getCurrentType(loc: Location): AppraiseType {
+ val current: String? = BlockStorage.getLocationInfo(loc, APPRAISE_TYPE_KEY)
+ var type: AppraiseType? = null
+ if (current != null) {
+ val key: NamespacedKey? = NamespacedKey.fromString(current, Bump.instance)
+ if (key != null) {
+ type = AppraiseType.getByKey(key)
+ }
+ }
+
+ if (type == null) {
+ type = BumpRegistry.appraiseTypes.first()
+ }
+ return type
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AppraiserSelector.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AppraiserSelector.kt
new file mode 100644
index 00000000..85d0a032
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AppraiserSelector.kt
@@ -0,0 +1,21 @@
+package io.github.slimefunguguproject.bump.implementation.items.machines
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.implementation.menu.AppraiseTypesMenu
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import org.bukkit.Material
+import java.util.function.Consumer
+
+internal class AppraiserSelector(
+ successCallback: Consumer,
+ backCallback: Runnable
+) : AppraiseTypesMenu(
+ Bump.localization.getLore("gui.appraise_type_selector_menu.title"),
+ successCallback,
+ backCallback
+) {
+
+ override fun getInfoItem() =
+ Bump.localization.getGuiItem(MaterialType.Material(Material.NAME_TAG), "APPRAISER_SELECTOR_INFO")
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.kt
new file mode 100644
index 00000000..046ad060
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/AttributeGrindstone.kt
@@ -0,0 +1,141 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.items.machines
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils
+import io.github.slimefunguguproject.bump.utils.tags.BumpTag
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import org.bukkit.Material
+import org.bukkit.NamespacedKey
+import org.bukkit.block.Block
+import org.bukkit.entity.Player
+import org.bukkit.inventory.EquipmentSlot
+import org.bukkit.inventory.ItemStack
+import org.bukkit.inventory.meta.ItemMeta
+
+class AttributeGrindstone(
+ itemGroup: ItemGroup,
+ item: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : SimpleMenuBlock(itemGroup, item, recipeType, recipe) {
+
+ companion object {
+
+ // energy
+ const val ENERGY_CONSUMPTION: Int = 1314
+ }
+
+ override val operationSlotItem = Bump.localization.getGuiItem(
+ MaterialType.Material(Material.NAME_TAG),
+ "ATTRIBUTE_GRINDSTONE_USE",
+ )
+
+ override fun getCapacity() = ENERGY_CONSUMPTION
+
+ override fun onOperate(menu: BlockMenu, b: Block, p: Player, action: ClickAction) {
+ grind(menu, p)
+ }
+
+ private fun grind(menu: BlockMenu, p: Player) {
+ val item = menu.getItemInSlot(INPUT_SLOT)
+
+ // null check
+ if (!ValidateUtils.noAirItem(item)) {
+ Bump.localization.sendMessage(p, "no-input")
+ BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p)
+ return
+ }
+
+ // check if input item is appraised
+ if (!AppraiseUtils.isAppraised(item)) {
+ Bump.localization.sendMessage(p, "machine.attribute-grindstone.invalid")
+ BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p)
+ return
+ }
+
+ // check output slot
+ if (menu.getItemInSlot(OUTPUT_SLOT) != null) {
+ Bump.localization.sendMessage(p, "output-no-space")
+ BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p)
+ return
+ }
+
+ // check energy
+ val charge = getCharge(menu.location)
+ if (charge < ENERGY_CONSUMPTION) {
+ Bump.localization.sendMessage(p, "not-enough-power")
+ BumpSound.ATTRIBUTE_GRINDSTONE_FAIL.playFor(p)
+ return
+ }
+
+ val output = item.clone()
+ clearAttributes(output)
+ menu.replaceExistingItem(INPUT_SLOT, null)
+ menu.pushItem(output, OUTPUT_SLOT)
+
+ setCharge(menu.location, 0)
+ Bump.localization.sendMessage(p, "machine.attribute-grindstone.success")
+ BumpSound.ATTRIBUTE_GRINDSTONE_SUCCEED.playFor(p)
+ }
+
+ private fun clearAttributes(itemStack: ItemStack) {
+ val meta = itemStack.itemMeta!!
+ // check the appraising version
+ val version = PersistentDataAPI.getByte(meta, Keys.APPRAISE_VERSION, 1.toByte())
+
+ removeModifiers(itemStack, meta, version)
+
+ // set pdc
+ PersistentDataAPI.setBoolean(meta, Keys.APPRAISABLE, true)
+ PersistentDataAPI.remove(meta, Keys.APPRAISE_LEVEL)
+
+ // set lore
+ val appraisedLore = ChatUtil.color(Bump.localization.getString("lores.appraised"))
+ val appraisedLorePrefix = appraisedLore.substring(0, appraisedLore.indexOf("{0}"))
+ val lore = if (meta.hasLore()) meta.lore!! else mutableListOf()
+ for (i in lore.indices) {
+ if (lore[i].startsWith(appraisedLorePrefix)) {
+ lore[i] = ChatUtil.color(Bump.localization.getString("lores.not-appraised"))
+ break
+ }
+ }
+ meta.lore = lore
+
+ // done
+ itemStack.setItemMeta(meta)
+ }
+
+ private fun removeModifiers(itemStack: ItemStack, meta: ItemMeta, version: Byte) {
+ if (version.toInt() == 1) {
+ // v1 legacy, remove all attribute modifiers
+ EquipmentSlot.entries.forEach {
+ if (BumpTag.getTag(it.name + "_SLOT")!!.isTagged(itemStack.type)) {
+ meta.removeAttributeModifier(it)
+ }
+ }
+ } else {
+ // v1, remove all bump attribute modifiers
+ val modifierMap = meta.attributeModifiers ?: return
+
+ for ((attribute, modifier) in modifierMap.entries()) {
+ val key = NamespacedKey.fromString(modifier.name, Bump.instance)
+ if (key != null && AppraiseType.getByKey(key) != null) {
+ meta.removeAttributeModifier(attribute, modifier)
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/ItemConverter.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/ItemConverter.kt
new file mode 100644
index 00000000..548808f6
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/ItemConverter.kt
@@ -0,0 +1,123 @@
+package io.github.slimefunguguproject.bump.implementation.items.machines
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.implementation.Slimefun
+import io.github.thebusybiscuit.slimefun4.libraries.dough.inventory.InvUtils
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset
+import net.guizhanss.guizhanlib.slimefun.machines.TickingMenuBlock
+import org.bukkit.Material
+import org.bukkit.block.Block
+import org.bukkit.inventory.ItemStack
+
+class ItemConverter(
+ itemGroup: ItemGroup,
+ item: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : TickingMenuBlock(itemGroup, item, recipeType, recipe) {
+
+ companion object {
+
+ // gui
+ private const val INFO_SLOT = 4
+
+ private val INPUT_SLOTS = intArrayOf(
+ 0, 1, 2, 3
+ )
+
+ private val OUTPUT_SLOTS = intArrayOf(
+ 5, 6, 7, 8
+ )
+
+ private val MAPPING = mapOf(
+ // materials
+ "SUN_ENERGY" to "PHOTOSYNTHETIC_ENERGY",
+ "MECHA_GEAR" to "MECHANICAL_GEAR",
+ "OLD_COIN" to "BROKEN_GOLD_COIN",
+ "MAKE" to "COMPUTER_TECH_CORE",
+ "OLD_CPU" to "BROKEN_CPU",
+ "CPU" to "CPU",
+ "SOUL_PAPER" to "ANCIENT_RUNE_SOUL",
+ "KSF_STUFF" to "INSTANT_NOODLE_SEASONING",
+ "WATER_SUGAR" to "POP_CANDY",
+ "PEACH_WOOD" to "PEACH_WOOD",
+ "UPDATE_POWER" to "UPDATE_CORE",
+ "COMPRESSED_RANDOM_EQUIPMENT" to "COMPRESSED_RANDOM_EQUIPMENT",
+
+ // food
+ "XUEBI" to "SPRITE",
+ "KELE" to "COLA",
+ "FANGBIANMIAN" to "INSTANT_NOODLE",
+ "LATIAO" to "SPICY_STRIPS",
+ "KOUXIANGTANG" to "CHEWING_GUM",
+ "ZONGZI" to "RICE_DUMPLING",
+
+ // tools
+ "GETGOLD_SPADE" to "GET_GOLD_SPADE",
+ "QUALITY_IDENTIFIER" to "QUALITY_IDENTIFIER",
+
+ // machines
+ "APPRAISAL" to "APPRAISER",
+ "ATTRIBUTE_GRINDSTONE" to "ATTRIBUTE_GRINDSTONE",
+
+ // armor
+ "RANDOM_HELMET" to "RANDOM_HELMET",
+ "RANDOM_HORSE_ARMOR" to "RANDOM_HORSE_ARMOR",
+
+ // weapons
+ "RANDOM_SWORD" to "RANDOM_SWORD",
+ "LIGHT_BOW" to "LIGHTNING_BOW",
+ "WITHERSKULL_BOW" to "WITHER_SKULL_BOW",
+ "EMER_SWORD" to "EMERALD_SWORD",
+ "BONE_SWORD" to "BONE_SWORD",
+ "GUARD_SWORD" to "GUARDIAN_SWORD",
+ "PEACH_SWORD" to "PEACH_WOOD_SWORD",
+ "SOUL_SWORD" to "SOUL_SWORD",
+ "SKY_SWORD" to "HEAVEN_BREAKING_SWORD",
+ "DEVIL_SWORD" to "DEMON_SLAYER_SWORD",
+ "SKY_DEVIL_SWORD" to "HEAVEN_BREAKING_DEMON_SLAYER_SWORD",
+ )
+ }
+
+ override fun getInputSlots() = INPUT_SLOTS
+
+ override fun getOutputSlots() = OUTPUT_SLOTS
+
+ override fun setup(preset: BlockMenuPreset) {
+ preset.addItem(INFO_SLOT, getInfoGui(), ChestMenuUtils.getEmptyClickHandler())
+ }
+
+ override fun tick(b: Block, menu: BlockMenu) {
+ for (inputSlot in INPUT_SLOTS) {
+ val input = menu.getItemInSlot(inputSlot)
+ if (!ValidateUtils.noAirItem(input)) continue
+ // get id
+ val id = Slimefun.getItemDataService().getItemData(input)
+ if (id.isEmpty) continue
+
+ // get output
+ val newIdPart = MAPPING[id.get()] ?: continue
+ val newId = Bump.localization.idPrefix + newIdPart
+ val output = input.clone()
+ Slimefun.getItemDataService().setItemData(output, newId)
+ Slimefun.getItemTextureService().setTexture(output, newId)
+
+ if (InvUtils.fits(menu.toInventory(), output, *OUTPUT_SLOTS)) {
+ menu.replaceExistingItem(inputSlot, null)
+ menu.pushItem(output, *OUTPUT_SLOTS)
+ }
+ }
+ }
+
+ private fun getInfoGui() = Bump.localization.getGuiItem(
+ MaterialType.Material(Material.BOOK),
+ "ITEM_CONVERTER_INFO",
+ )
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.kt
new file mode 100644
index 00000000..4259c267
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/machines/SimpleMenuBlock.kt
@@ -0,0 +1,83 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.items.machines
+
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent
+import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset
+import net.guizhanss.guizhanlib.slimefun.machines.MenuBlock
+import org.bukkit.block.Block
+import org.bukkit.entity.Player
+import org.bukkit.event.block.BlockBreakEvent
+import org.bukkit.inventory.ItemStack
+
+abstract class SimpleMenuBlock(
+ itemGroup: ItemGroup,
+ item: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : MenuBlock(itemGroup, item, recipeType, recipe), EnergyNetComponent {
+
+ companion object {
+
+ // gui
+ private val BACKGROUND = intArrayOf(
+ 0, 4, 8, 9, 17, 18, 22, 26
+ )
+ private val INPUT_BACKGROUND = intArrayOf(
+ 1, 2, 3, 10, 12, 19, 20, 21
+ )
+ private val OUTPUT_BACKGROUND = intArrayOf(
+ 5, 6, 7, 14, 16, 23, 24, 25
+ )
+
+ private const val OPERATION_SLOT = 13
+
+ @JvmStatic
+ protected val INPUT_SLOT = 11
+
+ @JvmStatic
+ protected val OUTPUT_SLOT = 15
+ }
+
+ protected abstract val operationSlotItem: ItemStack
+
+ protected abstract fun onOperate(menu: BlockMenu, b: Block, p: Player, action: ClickAction)
+
+ override fun setup(preset: BlockMenuPreset) {
+ preset.drawBackground(ChestMenuUtils.getBackground(), BACKGROUND)
+ preset.drawBackground(ChestMenuUtils.getInputSlotTexture(), INPUT_BACKGROUND)
+ preset.drawBackground(ChestMenuUtils.getOutputSlotTexture(), OUTPUT_BACKGROUND)
+
+ preset.addItem(OPERATION_SLOT, operationSlotItem)
+ preset.addMenuClickHandler(OPERATION_SLOT, ChestMenuUtils.getEmptyClickHandler())
+ }
+
+ override fun onBreak(e: BlockBreakEvent, menu: BlockMenu) {
+ super.onBreak(e, menu)
+ val location = menu.location
+ menu.dropItems(location, INPUT_SLOT)
+ menu.dropItems(location, OUTPUT_SLOT)
+ }
+
+ override fun onNewInstance(menu: BlockMenu, b: Block) {
+ super.onNewInstance(menu, b)
+ menu.addMenuClickHandler(OPERATION_SLOT) { p: Player, _: Int, _: ItemStack, clickAction: ClickAction ->
+ onOperate(menu, b, p, clickAction)
+ false
+ }
+ }
+
+ override fun getEnergyComponentType() = EnergyNetComponentType.CONSUMER
+
+ override fun getInputSlots() = intArrayOf(INPUT_SLOT)
+
+ override fun getOutputSlots() = intArrayOf(OUTPUT_SLOT)
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/materials/BumpMaterial.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/materials/BumpMaterial.kt
new file mode 100644
index 00000000..b159f275
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/materials/BumpMaterial.kt
@@ -0,0 +1,14 @@
+package io.github.slimefunguguproject.bump.implementation.items.materials
+
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock
+import org.bukkit.inventory.ItemStack
+
+class BumpMaterial(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : UnplaceableBlock(itemGroup, itemStack, recipeType, recipe)
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/GetGoldSpade.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/GetGoldSpade.kt
new file mode 100644
index 00000000..0b131d17
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/GetGoldSpade.kt
@@ -0,0 +1,41 @@
+package io.github.slimefunguguproject.bump.implementation.items.tools
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.implementation.BumpItems
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.EnchantmentX
+import net.guizhanss.guizhanlib.utils.RandomUtil
+import org.bukkit.Material
+import org.bukkit.event.block.BlockBreakEvent
+import org.bukkit.inventory.ItemStack
+import kotlin.math.min
+
+class GetGoldSpade(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : UnplaceableBlock(itemGroup, itemStack, recipeType, recipe) {
+
+ init {
+ addItemHandler(getToolUseHandler())
+ }
+
+ private fun getToolUseHandler() =
+ ToolUseHandler { e: BlockBreakEvent, item: ItemStack, _: Int, drops: MutableList ->
+ if (e.block.type != Material.SAND) return@ToolUseHandler
+
+ val luckLevel = min(item.getEnchantmentLevel(EnchantmentX.FORTUNE), 5)
+ if (!RandomUtil.testChance(30 + luckLevel * 10, 100)) return@ToolUseHandler
+
+ if (BumpItems.BROKEN_GOLD_COIN.item?.isDisabledIn(e.block.world) == true) return@ToolUseHandler
+
+ drops.clear()
+ drops.add(BumpItems.BROKEN_GOLD_COIN)
+ Bump.localization.sendActionbarMessage(e.player, "tool.get_gold_spade")
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.kt
new file mode 100644
index 00000000..2b0fba3e
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/tools/QualityIdentifier.kt
@@ -0,0 +1,214 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.items.tools
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils
+import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.LimitedUseItem
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils
+import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.MenuClickHandler
+import net.guizhanss.guizhanlib.minecraft.utils.InventoryUtil
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+
+/**
+ * A quality identifier can mark available [ItemStack]
+ * as appraisable.
+ *
+ * @author ybw0014
+ */
+class QualityIdentifier(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array
+) : LimitedUseItem(itemGroup, itemStack, recipeType, recipe) {
+
+ companion object {
+
+ const val MAX_USES = 5
+
+ // gui
+ private val BACKGROUND_SLOT = intArrayOf(
+ 0, 8, 9, 17, 18, 22, 26
+ )
+ private val INPUT_BORDER = intArrayOf(
+ 1, 2, 3, 10, 12, 19, 20, 21
+ )
+ private val OUTPUT_BORDER = intArrayOf(
+ 5, 6, 7, 14, 16, 23, 24, 25
+ )
+ private const val INFO_SLOT = 4
+ private const val INPUT_SLOT = 11
+ private const val APPRAISE_BUTTON = 13
+ private const val OUTPUT_SLOT = 15
+ }
+
+ init {
+ maxUseCount = MAX_USES
+ addItemHandler(itemHandler)
+ }
+
+ override fun getItemHandler() = ItemUseHandler { e: PlayerRightClickEvent ->
+ e.cancel()
+ val p = e.player
+ val paperItemStack = e.item
+
+ if (paperItemStack.type == Material.AIR) {
+ return@ItemUseHandler
+ }
+
+ if (paperItemStack.amount > 1) {
+ Bump.localization.sendMessage(p, "stacked")
+ return@ItemUseHandler
+ }
+
+ // Open menu
+ val menu = ChestMenu(paperItemStack.itemMeta!!.displayName)
+ createMenu(p, menu, paperItemStack)
+ menu.open(p)
+ }
+
+ private fun createMenu(p: Player, menu: ChestMenu, paperItemStack: ItemStack) {
+ menu.isPlayerInventoryClickable = true
+
+ // Open sound
+ menu.addMenuOpeningHandler { BumpSound.QUALITY_IDENTIFIER_OPEN.playFor(p) }
+
+ // Setup menu
+ for (i in BACKGROUND_SLOT) {
+ menu.addItem(i, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler())
+ }
+ for (i in INPUT_BORDER) {
+ menu.addItem(i, ChestMenuUtils.getInputSlotTexture(), ChestMenuUtils.getEmptyClickHandler())
+ }
+ for (i in OUTPUT_BORDER) {
+ menu.addItem(i, ChestMenuUtils.getOutputSlotTexture(), ChestMenuUtils.getEmptyClickHandler())
+ }
+
+ // Add status
+ menu.addItem(INFO_SLOT, getUsesLeftGui(getUsesLeft(paperItemStack)), ChestMenuUtils.getEmptyClickHandler())
+
+ // Add menu close handler
+ menu.addMenuCloseHandler { _: Player ->
+ InventoryUtil.push(p, menu.getItemInSlot(INPUT_SLOT))
+ InventoryUtil.push(p, menu.getItemInSlot(OUTPUT_SLOT))
+ }
+
+ // Block Quality identifier click
+ menu.addPlayerInventoryClickHandler { _, _, item: ItemStack?, _ ->
+ val sfItem = getByItem(item)
+ sfItem !is QualityIdentifier
+ }
+
+ // Add appraise button handler
+ menu.addItem(APPRAISE_BUTTON, getUseGui(), getAppraiseButtonHandler(p, menu, paperItemStack))
+ }
+
+ private fun getAppraiseButtonHandler(p: Player, menu: ChestMenu, paperItemStack: ItemStack) =
+ MenuClickHandler { _, _, _, _ ->
+ // Check input slot
+ val input = menu.getItemInSlot(INPUT_SLOT)
+
+ if (!ValidateUtils.noAirItem(input)) {
+ Bump.localization.sendMessage(p, "no-input")
+ BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(p)
+ return@MenuClickHandler false
+ }
+
+ // Check output slot
+ if (menu.getItemInSlot(OUTPUT_SLOT) != null) {
+ Bump.localization.sendMessage(p, "output-no-space")
+ BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(p)
+ return@MenuClickHandler false
+ }
+
+ // validate item
+ if (isValidItem(input)) {
+ // item can be marked appraisable
+ val output = input.clone()
+ AppraiseUtils.setAppraisable(output)
+ menu.replaceExistingItem(INPUT_SLOT, null)
+ menu.replaceExistingItem(OUTPUT_SLOT, output)
+
+ damageItem(p, paperItemStack)
+
+ /*
+ * The paper is used up, should close the gui.
+ * Otherwise, update the status slot.
+ */
+ if (paperItemStack.type == Material.AIR) {
+ p.closeInventory()
+ } else {
+ menu.replaceExistingItem(INFO_SLOT, getUsesLeftGui(getUsesLeft(paperItemStack)))
+
+ // play sound only if appraisal paper is not broken
+ BumpSound.QUALITY_IDENTIFIER_SUCCEED.playFor(p)
+ }
+
+ Bump.localization.sendMessage(p, "tool.quality_identifier.success")
+ } else {
+ Bump.localization.sendMessage(p, "tool.quality_identifier.invalid")
+ BumpSound.QUALITY_IDENTIFIER_FAIL.playFor(p)
+ }
+ false
+ }
+
+ /**
+ * Validate the item. The item that can be marked appraisable
+ * should meet these requirements:
+ * - is a valid item for any appraise type
+ * - has not been appraised yet
+ * - has not been marked appraisable yet
+ *
+ * @param itemStack The [ItemStack] to be validated.
+ *
+ * @return If the [ItemStack] is applicable to appraisal paper.
+ */
+ private fun isValidItem(itemStack: ItemStack): Boolean {
+ return if (BumpRegistry.appraiseTypes.any { it.isValidItem(itemStack) }) {
+ Bump.debug("Item is accepted by an appraise type: $itemStack")
+ Bump.debug("appraised: ${AppraiseUtils.isAppraised(itemStack)}")
+ Bump.debug("appraisable: ${AppraiseUtils.isAppraisable(itemStack)}")
+ !AppraiseUtils.isAppraised(itemStack) && !AppraiseUtils.isAppraisable(itemStack)
+ } else {
+ false
+ }
+ }
+
+ /**
+ * Get the uses left of the quality identifier.
+ */
+ private fun getUsesLeft(itemStack: ItemStack): Int {
+ return PersistentDataAPI.getInt(itemStack.itemMeta!!, storageKey, maxUseCount)
+ }
+
+ /**
+ * Get the GUI item to indicate the uses left.
+ */
+ private fun getUsesLeftGui(usesLeft: Int) =
+ CustomItemStack(Material.LIME_STAINED_GLASS_PANE, LoreBuilder.usesLeft(usesLeft))
+
+ /**
+ * Get the GUI item of use button.
+ */
+ private fun getUseGui(): ItemStack = Bump.localization.getGuiItem(
+ MaterialType.Material(Material.PAPER),
+ "QUALITY_IDENTIFIER_USE",
+ )
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.kt
new file mode 100644
index 00000000..5a27cb5b
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpBow.kt
@@ -0,0 +1,38 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.core.attributes.CostHungerItem
+import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem
+import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem
+import org.bukkit.inventory.ItemStack
+
+
+abstract class BumpBow(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int
+) : SimpleSlimefunItem(itemGroup, itemStack, recipeType, recipe), DamageableItem, CostHungerItem {
+
+ init {
+ require(hunger in 0..20) { "Hunger cost must be between 0 and 20" }
+ }
+
+ private val hungerCostSetting = IntRangeSetting(this, "hunger-cost", 0, hunger, 20)
+ private val costDurabilitySetting = ItemSetting(this, "cost-durability", true)
+
+ init {
+ addItemSetting(costDurabilitySetting)
+ addItemSetting(hungerCostSetting)
+ }
+
+ override fun isDamageable() = costDurabilitySetting.value
+
+ override fun getHungerCost() = hungerCostSetting.value
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.kt
new file mode 100644
index 00000000..7ee64f0e
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/BumpSword.kt
@@ -0,0 +1,65 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.attributes.CooldownItem
+import io.github.slimefunguguproject.bump.core.attributes.CostHungerItem
+import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+
+abstract class BumpSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : SimpleSlimefunItem(itemGroup, itemStack, recipeType, recipe), NotPlaceable, CostHungerItem,
+ CooldownItem {
+
+ init {
+ require(hunger in 0..20) { "Hunger cost must be between 0 and 20" }
+ }
+
+ private val hungerCostSetting = IntRangeSetting(this, "hunger-cost", 0, hunger, 20)
+ private val cooldownSetting = IntRangeSetting(this, "cooldown-in-seconds", 0, 0, Int.MAX_VALUE)
+
+ init {
+ addItemSetting(hungerCostSetting)
+ addItemSetting(cooldownSetting)
+ }
+
+ override fun getHungerCost() = hungerCostSetting.value
+
+ override fun getCooldown() = cooldownSetting.value
+
+ /**
+ * This function is called when player use this sword
+ *
+ * @param p the [Player] that uses this sword
+ * @param sword the [ItemStack] of this sword
+ */
+ abstract fun onItemUse(p: Player, sword: ItemStack)
+
+ override fun getItemHandler() = ItemUseHandler { e: PlayerRightClickEvent ->
+ val p = e.player
+ val item = e.item
+ if (isCooldown(item)) {
+ if (costHunger(p)) {
+ setCooldown(item)
+ onItemUse(p, item)
+ } else {
+ Bump.localization.sendActionbarMessage(p, "weapon.low-food-level")
+ }
+ } else {
+ Bump.localization.sendActionbarMessage(p, "weapon.cooldown")
+ }
+ }
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/DemonSlayerSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/DemonSlayerSword.kt
new file mode 100644
index 00000000..f7ab6370
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/DemonSlayerSword.kt
@@ -0,0 +1,33 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.ParticleX
+import org.bukkit.entity.Player
+import org.bukkit.entity.SmallFireball
+import org.bukkit.inventory.ItemStack
+
+class DemonSlayerSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : BumpSword(itemGroup, itemStack, recipeType, recipe, hunger) {
+
+ override fun onItemUse(p: Player, sword: ItemStack) {
+ Bump.localization.sendActionbarMessage(p, "weapon.demon_slayer_sword")
+
+ BumpSound.DEMON_SLAYER_SWORD_USE.playFor(p)
+
+ for (i in 0..19) {
+ val projectile = p.launchProjectile(SmallFireball::class.java)
+ WeaponProjectileTask.track(projectile)
+ p.spawnParticle(ParticleX.ENCHANT, p.location, 1)
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingDemonSlayerSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingDemonSlayerSword.kt
new file mode 100644
index 00000000..51e2c1b7
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingDemonSlayerSword.kt
@@ -0,0 +1,49 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.PotionEffectTypeX
+import org.bukkit.entity.DragonFireball
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+import org.bukkit.scheduler.BukkitRunnable
+
+class HeavenBreakingDemonSlayerSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : BumpSword(itemGroup, itemStack, recipeType, recipe, hunger) {
+
+ override fun onItemUse(p: Player, sword: ItemStack) {
+ Bump.localization.sendActionbarMessage(p, "weapon.heaven_breaking_demon_slayer_sword.activated")
+
+ p.isGlowing = true
+ p.addPotionEffect(PotionEffect(PotionEffectType.SPEED, 300, 3))
+ p.addPotionEffect(PotionEffect(PotionEffectTypeX.RESISTANCE, 300, 3))
+
+ object : BukkitRunnable() {
+ var count: Int = 3
+
+ override fun run() {
+ if (count > 0) {
+ BumpSound.HEAVEN_BREAKING_DEMON_SLAYER_SWORD_USE.playFor(p)
+ val projectile = p.launchProjectile(DragonFireball::class.java)
+ WeaponProjectileTask.track(projectile)
+ count--
+ } else {
+ cancel()
+ p.isGlowing = false
+ Bump.localization.sendActionbarMessage(p, "weapon.heaven_breaking_demon_slayer_sword.deactivated")
+ }
+ }
+ }.runTaskTimer(Bump.instance, 1L, 100L)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingSword.kt
new file mode 100644
index 00000000..4bea5d8b
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/HeavenBreakingSword.kt
@@ -0,0 +1,40 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.ParticleX
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import org.bukkit.util.Vector
+
+/**
+ * [Heaven Breaking Sword][HeavenBreakingSword] will lift player up to the sky when using.
+ *
+ * @author ybw0014
+ */
+class HeavenBreakingSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : BumpSword(itemGroup, itemStack, recipeType, recipe, hunger) {
+
+ override fun onItemUse(p: Player, sword: ItemStack) {
+ Bump.localization.sendActionbarMessage(p, "weapon.heaven_breaking_sword.activated")
+
+ // directly up
+ p.velocity = Vector(0, 3, 0)
+
+ BumpSound.HEAVEN_BREAKING_SWORD_USE.playFor(p)
+ for (i in 0..19) {
+ p.spawnParticle(ParticleX.EXPLOSION_EMITTER, p.location, 1)
+ }
+ PersistentDataAPI.setBoolean(p, Keys.HEAVEN_BREAKING_SWORD_PROTECTED, true)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/LightningBow.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/LightningBow.kt
new file mode 100644
index 00000000..62602525
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/LightningBow.kt
@@ -0,0 +1,41 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.event.entity.EntityShootBowEvent
+import org.bukkit.inventory.ItemStack
+
+class LightningBow(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : BumpBow(itemGroup, itemStack, recipeType, recipe, hunger) {
+
+ override fun getItemHandler() = BowUseHandler { e: EntityShootBowEvent, p: Player, item: ItemStack ->
+ e.isCancelled = true
+ val target = p.getTargetBlock(null, 200)
+ if (target.type == Material.AIR) {
+ return@BowUseHandler
+ }
+
+ val targetLocation = target.location
+ if (costHunger(p)) {
+ damageItem(p, item)
+
+ Bump.localization.sendActionbarMessage(p, "weapon.lightning_bow")
+
+ for (i in 0..9) {
+ p.world.strikeLightning(targetLocation)
+ }
+ } else {
+ Bump.localization.sendActionbarMessage(p, "weapon.low-food-level")
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/NormalSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/NormalSword.kt
new file mode 100644
index 00000000..ceebaae6
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/NormalSword.kt
@@ -0,0 +1,14 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock
+import org.bukkit.inventory.ItemStack
+
+class NormalSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+) : UnplaceableBlock(itemGroup, itemStack, recipeType, recipe)
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.kt
new file mode 100644
index 00000000..6cfa7fc9
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/SoulSword.kt
@@ -0,0 +1,51 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.utils.FoodLevelUtils
+import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler
+import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem
+import org.bukkit.attribute.Attribute
+import org.bukkit.inventory.ItemStack
+
+class SoulSword(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+) : SimpleSlimefunItem(itemGroup, itemStack, recipeType, recipe) {
+
+ override fun getItemHandler() = ItemUseHandler { e: PlayerRightClickEvent ->
+ val p = e.player
+ val health = p.health
+ val maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.value
+ val foodLevel = p.foodLevel
+
+ if (maxHealth <= health) {
+ Bump.localization.sendActionbarMessage(p, "weapon.unavailable")
+ return@ItemUseHandler
+ }
+ if (foodLevel >= 2) {
+ if (maxHealth - health <= foodLevel) {
+ // Food level can be partially converted to full health
+ FoodLevelUtils.set(p, (foodLevel - (maxHealth - health)).toInt())
+ p.health = maxHealth
+ Bump.localization.sendActionbarMessage(p, "weapon.soul_sword.converted-part")
+ } else {
+ // Food level can be all converted to health
+ FoodLevelUtils.set(p, 0)
+ p.health = health + foodLevel
+ Bump.localization.sendActionbarMessage(p, "weapon.soul_sword.converted-all")
+ }
+
+ BumpSound.SOUL_SWORD_USE.playFor(p)
+ } else {
+ Bump.localization.sendActionbarMessage(p, "weapon.low-food-level")
+ }
+ }
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.kt
new file mode 100644
index 00000000..2329b730
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/items/weapons/WitherSkullBow.kt
@@ -0,0 +1,38 @@
+package io.github.slimefunguguproject.bump.implementation.items.weapons
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler
+import io.github.slimefunguguproject.bump.core.services.sounds.BumpSound
+import io.github.slimefunguguproject.bump.implementation.tasks.WeaponProjectileTask
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import org.bukkit.entity.Player
+import org.bukkit.entity.WitherSkull
+import org.bukkit.event.entity.EntityShootBowEvent
+import org.bukkit.inventory.ItemStack
+
+class WitherSkullBow(
+ itemGroup: ItemGroup,
+ itemStack: SlimefunItemStack,
+ recipeType: RecipeType,
+ recipe: Array,
+ hunger: Int,
+) : BumpBow(itemGroup, itemStack, recipeType, recipe, hunger) {
+
+ override fun getItemHandler() = BowUseHandler { e: EntityShootBowEvent, p: Player, item: ItemStack ->
+ e.isCancelled = true
+ if (costHunger(p)) {
+ damageItem(p, item)
+
+ Bump.localization.sendActionbarMessage(p, "weapon.wither_skull_bow")
+
+ BumpSound.WITHER_SKULL_BOW_USE.playFor(p)
+
+ val projectile = p.launchProjectile(WitherSkull::class.java)
+ WeaponProjectileTask.track(projectile)
+ } else {
+ Bump.localization.sendActionbarMessage(p, "weapon.low-food-level")
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.kt
new file mode 100644
index 00000000..59976940
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/BowShootListener.kt
@@ -0,0 +1,27 @@
+package io.github.slimefunguguproject.bump.implementation.listeners
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.core.handlers.BowUseHandler
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
+import org.bukkit.entity.Arrow
+import org.bukkit.entity.Player
+import org.bukkit.event.EventHandler
+import org.bukkit.event.Listener
+import org.bukkit.event.entity.EntityShootBowEvent
+
+class BowShootListener(plugin: Bump) : Listener {
+ init {
+ plugin.server.pluginManager.registerEvents(this, plugin)
+ }
+
+ @EventHandler
+ fun onBowUse(e: EntityShootBowEvent) {
+ if (e.entity is Player && e.projectile is Arrow) {
+ val bow = SlimefunItem.getByItem(e.bow)
+
+ bow?.callItemHandler(BowUseHandler::class.java) { handler: BowUseHandler ->
+ handler.onUse(e, e.entity as Player, e.bow!!)
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.kt
new file mode 100644
index 00000000..90b3b6e2
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/DragonBreathListener.kt
@@ -0,0 +1,28 @@
+package io.github.slimefunguguproject.bump.implementation.listeners
+
+import io.github.slimefunguguproject.bump.Bump
+import org.bukkit.Particle
+import org.bukkit.entity.AreaEffectCloud
+import org.bukkit.entity.Player
+import org.bukkit.event.EventHandler
+import org.bukkit.event.Listener
+import org.bukkit.event.entity.EntityDamageByEntityEvent
+
+class DragonBreathListener(plugin: Bump) : Listener {
+ init {
+ plugin.server.pluginManager.registerEvents(this, plugin)
+ }
+
+ @EventHandler
+ fun onPlayerDamaged(e: EntityDamageByEntityEvent) {
+ val damager = e.damager
+ if (damager is AreaEffectCloud
+ && damager.particle == Particle.DRAGON_BREATH
+ && damager.source is Player
+ && e.entity is Player
+ && (damager.source as Player).uniqueId == e.entity.uniqueId
+ ) {
+ e.isCancelled = true
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/HeavenBreakingSwordListener.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/HeavenBreakingSwordListener.kt
new file mode 100644
index 00000000..54e8dc17
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/listeners/HeavenBreakingSwordListener.kt
@@ -0,0 +1,38 @@
+package io.github.slimefunguguproject.bump.implementation.listeners
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import org.bukkit.entity.Monster
+import org.bukkit.entity.Player
+import org.bukkit.event.EventHandler
+import org.bukkit.event.Listener
+import org.bukkit.event.entity.EntityDamageEvent
+
+class HeavenBreakingSwordListener(plugin: Bump) : Listener {
+ init {
+ plugin.server.pluginManager.registerEvents(this, plugin)
+ }
+
+ @EventHandler
+ fun onPlayerHitGround(e: EntityDamageEvent) {
+ val p = e.entity
+ if (p !is Player) return
+ if (e.cause == EntityDamageEvent.DamageCause.FALL
+ && PersistentDataAPI.getBoolean(p, Keys.HEAVEN_BREAKING_SWORD_PROTECTED)
+ ) {
+ // cancel fall damage
+ e.isCancelled = true
+ Bump.localization.sendActionbarMessage(p, "weapon.sky_sword.protected")
+ PersistentDataAPI.setBoolean(p, Keys.HEAVEN_BREAKING_SWORD_PROTECTED, false)
+
+ // distribute damage evenly to nearby hostiles
+ val damage = e.damage
+ if (damage <= 0) return
+ val nearbyHostiles = p.world.getNearbyEntities(p.location, 5.0, 5.0, 5.0) { it is Monster }
+ if (nearbyHostiles.isEmpty()) return
+ val damagePerHostile = damage / nearbyHostiles.size
+ nearbyHostiles.forEach { (it as Monster).damage(damagePerHostile, p) }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypeMenu.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypeMenu.kt
new file mode 100644
index 00000000..134b06c6
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypeMenu.kt
@@ -0,0 +1,175 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.menu
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseAttribute
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.utils.GeneralUtils
+import io.github.slimefunguguproject.bump.utils.items.AppraiseUtils
+import io.github.slimefunguguproject.bump.utils.items.MaterialType
+import io.github.slimefunguguproject.bump.utils.items.buildDisplayItem
+import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect
+import io.github.thebusybiscuit.slimefun4.implementation.Slimefun
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu
+import org.bukkit.ChatColor
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import kotlin.math.min
+
+class AppraiseTypeMenu(
+ private val appraiseType: AppraiseType,
+ private val backCallback: Runnable,
+) {
+
+ companion object {
+
+ private const val GUIDE_BACK = 0
+
+ private const val INFO_SLOT = 4
+
+ private const val EQUIPMENT_TYPE_SLOT = 12
+ private const val MATERIAL_SLOT = 13
+ private const val EQUIPMENT_SLOT_SLOT = 14
+
+ private const val ATTRIBUTES_START = 27
+ }
+
+ /**
+ * Open the menu to [Player].
+ *
+ * @param p The [Player] to open the menu to.
+ */
+ fun open(p: Player) {
+ val chestMenu = ChestMenu(appraiseType.name)
+ setupMenu(p, chestMenu)
+ chestMenu.open(p)
+ }
+
+ private fun setupMenu(player: Player, menu: ChestMenu) {
+ menu.isEmptySlotsClickable = false
+
+ // Sound
+ menu.addMenuOpeningHandler { p -> SoundEffect.GUIDE_BUTTON_CLICK_SOUND.playFor(p) }
+
+ // Back
+ menu.addItem(
+ GUIDE_BACK, ChestMenuUtils.getBackButton(
+ player,
+ "",
+ ChatColor.GRAY.toString() + Slimefun.getLocalization().getMessage(player, "guide.back.guide")
+ )
+ )
+ menu.addMenuClickHandler(GUIDE_BACK) { _, _, _, _ ->
+ backCallback.run()
+ false
+ }
+
+ menu.addItem(INFO_SLOT, getAppraiseInfoItem(appraiseType))
+ menu.addMenuClickHandler(INFO_SLOT, ChestMenuUtils.getEmptyClickHandler())
+
+ menu.addItem(EQUIPMENT_TYPE_SLOT, getEquipmentTypeItem(appraiseType))
+ menu.addMenuClickHandler(EQUIPMENT_TYPE_SLOT, ChestMenuUtils.getEmptyClickHandler())
+
+ menu.addItem(MATERIAL_SLOT, getMaterialItem(appraiseType))
+ menu.addMenuClickHandler(MATERIAL_SLOT, ChestMenuUtils.getEmptyClickHandler())
+
+ menu.addItem(EQUIPMENT_SLOT_SLOT, getEquipmentSlotItem(appraiseType))
+ menu.addMenuClickHandler(EQUIPMENT_SLOT_SLOT, ChestMenuUtils.getEmptyClickHandler())
+
+ var slot = ATTRIBUTES_START
+ for (attribute in appraiseType.attributes) {
+ menu.addItem(slot, getAppraiseAttributeItem(attribute))
+ menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler())
+
+ slot++
+ if (slot > 53) {
+ break
+ }
+ }
+ }
+
+ private fun getAppraiseInfoItem(type: AppraiseType): ItemStack {
+ return buildDisplayItem {
+ material = MaterialType.Material(Material.ANVIL)
+ name = type.name
+ lore = AppraiseUtils.getDescriptionLore(type)
+ }
+ }
+
+ private fun getEquipmentTypeItem(type: AppraiseType): ItemStack {
+ val equipmentType = type.equipmentType.toString()
+ return buildDisplayItem {
+ material = MaterialType.Material(Material.DIAMOND_SWORD)
+ name = Bump.localization.getLore("appraise_info.equipment_type.name", equipmentType)
+ lore = listOf(Bump.localization.getLore("appraise_info.equipment_type.${equipmentType.lowercase()}"))
+ }
+ }
+
+ private fun getMaterialItem(type: AppraiseType): ItemStack {
+ val result: ItemStack
+ if (type.checkMaterial) {
+ // Enabled checking material, display materials as well (cap at 10)
+ val matLore: MutableList = mutableListOf(
+ Bump.localization.getLore("appraise_info.material.enabled"),
+ ""
+ )
+
+ val materials = type.validMaterials.toList()
+ val size = min(materials.size, 10)
+
+ materials.subList(0, size).forEach {
+ matLore.add("${ChatColor.GRAY}${GeneralUtils.getMaterialName(it)}")
+ }
+
+ if (materials.size > 10) {
+ matLore.add(
+ Bump.localization.getLore("appraise_info.material.enabled_more", materials.size - size)
+ )
+ }
+
+ result = buildDisplayItem {
+ material = MaterialType.Material(Material.FILLED_MAP)
+ name = Bump.localization.getLore("appraise_info.material.name")
+ lore = matLore
+ }
+ } else {
+ result = buildDisplayItem {
+ material = MaterialType.Material(Material.MAP)
+ name = Bump.localization.getLore("appraise_info.material.name")
+ lore = listOf(Bump.localization.getLore("appraise_info.material.disabled"))
+ }
+ }
+ return result
+ }
+
+ private fun getEquipmentSlotItem(type: AppraiseType): ItemStack {
+ val itemLore = mutableListOf(
+ Bump.localization.getLore("appraise_info.equipment_slot.lore"),
+ ""
+ )
+
+ type.validEquipmentSlots.forEach {
+ itemLore.add(ChatColor.GRAY.toString() + it.toString())
+ }
+
+ return buildDisplayItem {
+ material = MaterialType.Material(Material.IRON_CHESTPLATE)
+ name = Bump.localization.getLore("appraise_info.equipment_slot.name")
+ lore = itemLore
+ }
+ }
+
+ private fun getAppraiseAttributeItem(attribute: AppraiseAttribute): ItemStack {
+ return buildDisplayItem {
+ material = MaterialType.Material(Material.PAPER)
+ name = Bump.localization.getLore("appraise_info.attribute.name", attribute.attribute.toString())
+ lore = listOf(
+ Bump.localization.getLore("appraise_info.attribute.range", attribute.min, attribute.max),
+ Bump.localization.getLore("appraise_info.attribute.weight", attribute.weight),
+ )
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypesMenu.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypesMenu.kt
new file mode 100644
index 00000000..684cb146
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/menu/AppraiseTypesMenu.kt
@@ -0,0 +1,150 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.menu
+
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect
+import io.github.thebusybiscuit.slimefun4.implementation.Slimefun
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils
+import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu
+import org.bukkit.ChatColor
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.inventory.ItemStack
+import java.util.function.Consumer
+import kotlin.math.ceil
+import kotlin.math.min
+
+/**
+ * This class will open a menu with all [AppraiseType].
+ *
+ * @author ybw0014
+ */
+abstract class AppraiseTypesMenu(
+ private val name: String,
+ private val successCallback: Consumer,
+ private val backCallback: Runnable
+) {
+
+ companion object {
+
+ private const val PAGE_SIZE = 36
+
+ private const val GUIDE_BACK = 1
+ private const val GUIDE_INFO = 4
+
+ private const val PAGE_PREVIOUS = 46
+ private const val PAGE_NEXT = 52
+
+ private val HEADER = intArrayOf(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8
+ )
+ private val FOOTER = intArrayOf(
+ 45, 46, 47, 48, 49, 50, 51, 52, 53
+ )
+ }
+
+ /**
+ * Return the [ItemStack] to display the information of the current page.
+ */
+ abstract fun getInfoItem(): ItemStack
+
+ /**
+ * Open the menu to [Player].
+ *
+ * @param p The [Player] to open the menu to.
+ */
+ fun open(p: Player) {
+ val chestMenu = ChestMenu(name)
+
+ for (slot in HEADER) {
+ chestMenu.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler())
+ }
+ for (slot in FOOTER) {
+ chestMenu.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler())
+ }
+
+ chestMenu.isEmptySlotsClickable = false
+ displayCollection(p, chestMenu, 1)
+ chestMenu.open(p)
+ }
+
+ private fun displayCollection(p: Player, menu: ChestMenu, page: Int) {
+ val appraiseTypes = BumpRegistry.appraiseTypes
+ .filter { type -> type.hasPermission(p) }
+ .toList()
+ val total = appraiseTypes.size
+ val totalPages = ceil(total / PAGE_SIZE.toDouble()).toInt()
+ val start = (page - 1) * PAGE_SIZE
+ val end = min(start + PAGE_SIZE, total)
+
+ val subList = appraiseTypes.subList(start, end)
+
+ // header & footer
+ menu.replaceExistingItem(GUIDE_INFO, getInfoItem())
+ setupFooter(p, menu, page, totalPages)
+
+ // Sound
+ SoundEffect.GUIDE_BUTTON_CLICK_SOUND.playFor(p)
+
+ // Back
+ menu.replaceExistingItem(
+ GUIDE_BACK, ChestMenuUtils.getBackButton(
+ p,
+ "",
+ ChatColor.GRAY.toString() + Slimefun.getLocalization().getMessage(p, "guide.back.guide")
+ )
+ )
+ menu.addMenuClickHandler(GUIDE_BACK) { _, _, _, _ ->
+ backCallback.run()
+ false
+ }
+
+ // list appraise types
+ for (i in 0 until PAGE_SIZE) {
+ val slot = i + 9
+
+ if (i + 1 <= subList.size) {
+ val appraiseType = subList[i]
+ menu.replaceExistingItem(slot, getDisplayItem(appraiseType))
+ menu.addMenuClickHandler(slot) { _, _, _, _ ->
+ successCallback.accept(appraiseType)
+ false
+ }
+ } else {
+ menu.replaceExistingItem(slot, null)
+ menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler())
+ }
+ }
+ }
+
+ private fun setupFooter(player: Player, menu: ChestMenu, page: Int, totalPages: Int) {
+ menu.replaceExistingItem(PAGE_PREVIOUS, ChestMenuUtils.getPreviousButton(player, page, totalPages))
+ menu.addMenuClickHandler(PAGE_PREVIOUS) { p: Player, _, _, _ ->
+ val previousPage = page - 1
+ if (previousPage >= 1) {
+ displayCollection(p, menu, previousPage)
+ }
+ false
+ }
+
+ menu.replaceExistingItem(PAGE_NEXT, ChestMenuUtils.getNextButton(player, page, totalPages))
+ menu.addMenuClickHandler(PAGE_NEXT) { p: Player, _, _, _ ->
+ val nextPage = page + 1
+ if (nextPage <= totalPages) {
+ displayCollection(p, menu, nextPage)
+ }
+ false
+ }
+ }
+
+ private fun getDisplayItem(type: AppraiseType): ItemStack {
+ return CustomItemStack(
+ Material.PAPER,
+ type.name,
+ type.description
+ )
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/recipes/BumpRecipeTypes.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/recipes/BumpRecipeTypes.kt
new file mode 100644
index 00000000..0d97e420
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/recipes/BumpRecipeTypes.kt
@@ -0,0 +1,20 @@
+package io.github.slimefunguguproject.bump.implementation.recipes
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.constant.Keys.createKey
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack
+import org.bukkit.Material
+
+
+object BumpRecipeTypes {
+
+ val GET_GOLD_SPADE: RecipeType = RecipeType(
+ "get_gold_spade".createKey(),
+ CustomItemStack(
+ Material.GOLDEN_SHOVEL,
+ Bump.localization.getItemName("_RECIPE_GET_GOLD_SPADE"),
+ Bump.localization.getItemLore("_RECIPE_GET_GOLD_SPADE")
+ )
+ )
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.kt
new file mode 100644
index 00000000..6b9063d4
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/AppraiseSetup.kt
@@ -0,0 +1,143 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.implementation.setup
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.api.appraise.EquipmentType
+import io.github.slimefunguguproject.bump.core.BumpRegistry
+import io.github.slimefunguguproject.bump.utils.ConfigUtils
+import io.github.slimefunguguproject.bump.utils.GeneralUtils.valueOfOrNull
+import io.github.slimefunguguproject.bump.utils.checkConditions
+import io.github.slimefunguguproject.bump.utils.constant.Keys.createKey
+import org.bukkit.ChatColor
+import org.bukkit.Material
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier.Operation
+import org.bukkit.inventory.EquipmentSlot
+import java.util.logging.Level
+
+object AppraiseSetup {
+
+ fun setup() {
+ setupStars()
+ setupTypes()
+ }
+
+ private fun setupTypes() {
+ Bump.log(Level.INFO, "Loading appraise types...")
+
+ val config = Bump.configService.appraiseTypes
+ if (config == null || config.getKeys(false).isEmpty()) {
+ Bump.log(Level.WARNING, "No appraise types found in config, some features may not work.")
+ return
+ }
+
+ for (type in config.getKeys(false)) {
+ Bump.log(Level.INFO, "Loading appraise type $type...")
+ if (!config.getBoolean("$type.enabled")) {
+ Bump.log(Level.INFO, "Appraise type $type is disabled.")
+ continue
+ }
+
+ try {
+ // conditions first
+ val conditions = config.getStringList("$type.conditions")
+ if (!checkConditions(conditions)) {
+ Bump.log(Level.INFO, "Appraise type \"$type\" is disabled due to conditions.")
+ continue
+ }
+
+ // raw values
+ val name = config.getString("$type.name") ?: error("Missing name")
+ val description = config.getStringList("$type.description")
+ val permission = config.getString("$type.permission")
+ val equipmentTypeStr = config.getString("$type.equipment-type", "ANY")!!
+ val checkMaterial = config.getBoolean("$type.check-material")
+ val validMaterials = config.getStringList("$type.materials")
+ val validSlimefunItemIds = config.getStringList("$type.slimefun-items")
+ val validEquipmentSlots = config.getStringList("$type.equipment-slots")
+ val attributesSection =
+ config.getConfigurationSection("$type.attributes") ?: error("Missing attributes")
+ val attributes = attributesSection.getKeys(false)
+
+ // parsed values
+ val equipmentType = valueOfOrNull(equipmentTypeStr) ?: error("Invalid equipment type")
+ val equipmentSlots: Set = ConfigUtils.parseEquipmentSlots(validEquipmentSlots)
+ val materials: Set = ConfigUtils.parseMaterials(validMaterials)
+
+ val appraiseTypeBuilder = AppraiseType.Builder(type.createKey())
+ .name(ChatColor.YELLOW.toString() + name)
+ .permission(permission)
+ .description(description.map { ChatColor.GRAY.toString() + it })
+ .equipmentType(equipmentType)
+ .validEquipmentSlots(equipmentSlots)
+ .checkMaterial(checkMaterial)
+ .validMaterials(materials)
+ .validSlimefunItemIds(validSlimefunItemIds)
+
+ for (attr in attributes) {
+ val attribute = Attribute.valueOf(attr)
+ val min = attributesSection.getDouble("$attr.min")
+ val max = attributesSection.getDouble("$attr.max")
+ val weightStr = attributesSection.getString("$attr.weight", "-1.0")!!
+ val operationStr = attributesSection.getString("$attr.operation", "ADD_NUMBER")!!
+ val weight = try {
+ weightStr.toDouble()
+ } catch (_: NumberFormatException) {
+ -1.0
+ }
+ val operation = try {
+ Operation.valueOf(operationStr)
+ } catch (_: IllegalArgumentException) {
+ Operation.ADD_NUMBER
+ }
+ appraiseTypeBuilder.attribute(attribute, min, max, weight, operation)
+ }
+
+ val appraiseType = appraiseTypeBuilder.build(Bump.instance)
+ Bump.log(Level.INFO, "Loaded appraise type \"$type\"")
+ Bump.debug(appraiseType.toString())
+ } catch (ex: Exception) {
+ Bump.log(Level.SEVERE, ex, "Failed to load appraise type \"$type\"")
+ }
+ }
+ }
+
+ private fun setupStars() {
+ val starThreshold = BumpRegistry.starThresholds
+ val starMap = Bump.configService.appraiseStars
+ if (starMap.isEmpty()) {
+ Bump.log(Level.INFO, "Invalid appraise stars in config. Using default values.")
+ setDefaultStarThreshold(starThreshold)
+ return
+ }
+
+ try {
+ for ((key, value) in starMap.entries) {
+ require(!(key < 0 || key > 100))
+ require(!(value < 0 || value > 127))
+ }
+ } catch (ex: IllegalArgumentException) {
+ Bump.log(Level.INFO, "Invalid appraise stars in config. Using default values.")
+ setDefaultStarThreshold(starThreshold)
+ }
+ starThreshold.clear()
+ starThreshold.putAll(starMap)
+ }
+
+ private fun setDefaultStarThreshold(starThreshold: MutableMap) {
+ starThreshold.clear()
+ starThreshold[100.toByte()] = 20.toByte()
+ starThreshold[98.toByte()] = 10.toByte()
+ starThreshold[96.toByte()] = 9.toByte()
+ starThreshold[92.toByte()] = 8.toByte()
+ starThreshold[88.toByte()] = 7.toByte()
+ starThreshold[82.toByte()] = 6.toByte()
+ starThreshold[74.toByte()] = 5.toByte()
+ starThreshold[64.toByte()] = 4.toByte()
+ starThreshold[48.toByte()] = 3.toByte()
+ starThreshold[30.toByte()] = 2.toByte()
+ starThreshold[10.toByte()] = 1.toByte()
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.kt
new file mode 100644
index 00000000..e7c69340
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/setup/ResearchSetup.kt
@@ -0,0 +1,96 @@
+package io.github.slimefunguguproject.bump.implementation.setup
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.implementation.BumpItems
+import io.github.slimefunguguproject.bump.utils.constant.Keys.createKey
+import io.github.thebusybiscuit.slimefun4.api.researches.Research
+import org.bukkit.inventory.ItemStack
+
+object ResearchSetup {
+
+ private var researchId = 114514
+
+ fun setup() {
+ createResearch(
+ "materials",
+ 25,
+ BumpItems.PHOTOSYNTHETIC_ENERGY,
+ BumpItems.MECHANICAL_GEAR,
+ BumpItems.COMPUTER_TECH_CORE,
+ BumpItems.BROKEN_CPU,
+ BumpItems.CPU,
+ BumpItems.ANCIENT_RUNE_SOUL,
+ BumpItems.INSTANT_NOODLE_SEASONING,
+ BumpItems.POP_CANDY,
+ BumpItems.UPDATE_CORE,
+ )
+
+ createResearch(
+ "food",
+ 18,
+ BumpItems.SPRITE,
+ BumpItems.COLA,
+ BumpItems.INSTANT_NOODLE,
+ BumpItems.SPICY_STRIPS,
+ BumpItems.CHEWING_GUM,
+ BumpItems.RICE_DUMPLING,
+ )
+
+ createResearch(
+ "get_gold",
+ 30,
+ BumpItems.GET_GOLD_SPADE,
+ BumpItems.BROKEN_GOLD_COIN
+ )
+
+ createResearch(
+ "appraise",
+ 50,
+ BumpItems.QUALITY_IDENTIFIER,
+ BumpItems.APPRAISER,
+ BumpItems.ATTRIBUTE_GRINDSTONE,
+ )
+
+ createResearch(
+ "random_equipment",
+ 45,
+ BumpItems.RANDOM_HELMET,
+ BumpItems.RANDOM_CHESTPLATE,
+ BumpItems.RANDOM_LEGGINGS,
+ BumpItems.RANDOM_BOOTS,
+ BumpItems.RANDOM_HORSE_ARMOR,
+ BumpItems.RANDOM_SWORD,
+ )
+
+ createResearch(
+ "bow",
+ 30,
+ BumpItems.LIGHTNING_BOW,
+ BumpItems.WITHER_SKULL_BOW,
+ )
+
+ createResearch(
+ "peach_sword",
+ 24,
+ BumpItems.PEACH_WOOD,
+ BumpItems.PEACH_WOOD_SWORD,
+ )
+
+ createResearch("normal_sword", 20, BumpItems.EMERALD_SWORD, BumpItems.BONE_SWORD, BumpItems.GUARDIAN_SWORD)
+
+ createResearch("soul_sword", 10, BumpItems.SOUL_SWORD)
+
+ createResearch(
+ "heaven_hell",
+ 33,
+ BumpItems.HEAVEN_BREAKING_SWORD,
+ BumpItems.DEMON_SLAYER_SWORD,
+ BumpItems.HEAVEN_BREAKING_DEMON_SLAYER_SWORD,
+ )
+ }
+
+ private fun createResearch(key: String, cost: Int, vararg itemStacks: ItemStack) {
+ Research("research_$key".createKey(), ++researchId, Bump.localization.getResearchName("key"), cost)
+ .addItems(*itemStacks).register()
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.kt
new file mode 100644
index 00000000..acfc85ed
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/implementation/tasks/WeaponProjectileTask.kt
@@ -0,0 +1,51 @@
+package io.github.slimefunguguproject.bump.implementation.tasks
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.thebusybiscuit.slimefun4.implementation.Slimefun
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import org.bukkit.entity.Projectile
+
+object WeaponProjectileTask : Runnable {
+
+ private val projectileMap: MutableMap = HashMap()
+
+ /**
+ * This method starts this task
+ */
+ fun start() {
+ val duration = Bump.configService.weaponProjectileDuration
+ if (duration > 0) {
+ Bump.scheduler().repeat(Slimefun.getTickerTask().tickRate, this)
+ }
+ }
+
+ /**
+ * This method will add [Projectile] to tracking list.
+ *
+ * @param projectile the [Projectile] to be added.
+ */
+ fun track(projectile: Projectile) {
+ projectileMap[projectile] = Bump.sfTickCount()
+ PersistentDataAPI.setBoolean(projectile, Keys.PROJECTILE, true)
+ }
+
+ override fun run() {
+ val currentTick = Bump.sfTickCount()
+
+ val it = projectileMap.entries.iterator()
+ while (it.hasNext()) {
+ val entry = it.next()
+ if (entry.value + Bump.configService.weaponProjectileDuration < currentTick) {
+ val projectile = entry.key
+ if (projectile.isValid) {
+ projectile.remove()
+ }
+ it.remove()
+ }
+ }
+ }
+
+
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConditionUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConditionUtils.kt
new file mode 100644
index 00000000..3e7ee408
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConditionUtils.kt
@@ -0,0 +1,55 @@
+package io.github.slimefunguguproject.bump.utils
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.thebusybiscuit.slimefun4.libraries.dough.versions.MinecraftVersion
+import io.github.thebusybiscuit.slimefun4.libraries.dough.versions.SemanticVersion
+import java.util.logging.Level
+
+private val mcVersion = MinecraftVersion.get()
+
+/**
+ * Check whether all the conditions are met.
+ */
+fun checkConditions(conditions: List): Boolean {
+ if (conditions.isEmpty()) return true
+
+ for (condition in conditions) {
+ Bump.debug("processing condition: $condition")
+ val parts = condition.split(" ")
+ when (parts[0]) {
+ "v" -> {
+ if (parts.size != 3) {
+ Bump.log(Level.WARNING, "Invalid condition: $condition")
+ continue
+ }
+ if (checkVersionCondition(parts[1], parts[2]) == false) return false
+ }
+
+ else -> {
+ Bump.log(Level.WARNING, "Unknown condition: $condition")
+ continue
+ }
+ }
+ }
+
+ return true
+}
+
+private fun checkVersionCondition(sub: String, version: String): Boolean? {
+ val target = try {
+ SemanticVersion.parse(version)
+ } catch (e: IllegalArgumentException) {
+ Bump.log(Level.WARNING, "Invalid version: $version")
+ return null
+ }
+
+ val targetVersion = MinecraftVersion(target.majorVersion, target.minorVersion, target.patchVersion)
+ return when (sub) {
+ ">=" -> mcVersion >= targetVersion
+ "<" -> mcVersion < targetVersion
+ else -> {
+ Bump.log(Level.WARNING, "Invalid version condition: $sub")
+ null
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConfigUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConfigUtils.kt
new file mode 100644
index 00000000..ce29054e
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/ConfigUtils.kt
@@ -0,0 +1,75 @@
+package io.github.slimefunguguproject.bump.utils
+
+import io.github.slimefunguguproject.bump.utils.GeneralUtils.valueOfOrNull
+import io.github.slimefunguguproject.bump.utils.constant.Patterns
+import io.github.slimefunguguproject.bump.utils.tags.BumpTag
+import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate
+import io.github.thebusybiscuit.slimefun4.libraries.dough.common.CommonPatterns
+import org.bukkit.Material
+import org.bukkit.configuration.InvalidConfigurationException
+import org.bukkit.inventory.EquipmentSlot
+import org.bukkit.plugin.Plugin
+import java.io.File
+
+object ConfigUtils {
+
+ fun saveDefaultFile(plugin: Plugin, fileName: String) {
+ val file = File(plugin.dataFolder, fileName)
+ if (!file.exists()) {
+ plugin.saveResource(fileName, false)
+ }
+ }
+
+ /**
+ * This method will parse [List] of material [String] into
+ * [Set] of [Material].
+ *
+ * Acceptable elements: minecraft materials, bump tags.
+ *
+ * @param materialList The [List] of material [String] to be parsed.
+ *
+ * @return The parsed [Set] of [Material].
+ *
+ * @throws IllegalArgumentException when the list is `null` or contains null elements.
+ * @throws InvalidConfigurationException when the list contains invalid material or BumpTag.
+ * @see BumpTag
+ */
+ fun parseMaterials(materialList: List): Set {
+ Validate.noNullElements(materialList)
+
+ val materials: MutableSet = HashSet()
+ for (value in materialList) {
+ if (Patterns.MINECRAFT_NAMESPACEDKEY.matcher(value).matches()) {
+ val material = Material.matchMaterial(value)
+
+ materials.add(material ?: throw InvalidConfigurationException("Invalid minecraft material: $value"))
+ } else if (Patterns.BUMP_TAG_CONFIG.matcher(value).matches()) {
+ val keyValue = CommonPatterns.COLON.split(value)[1].uppercase()
+ val tag = BumpTag.getTag(keyValue)
+
+ materials.addAll(tag?.values ?: throw InvalidConfigurationException("Invalid BumpTag: $keyValue"))
+ }
+ }
+ return materials
+ }
+
+ /**
+ * This method will parse [List] of equipment slot [String] into
+ * [Set] of [EquipmentSlot].
+ *
+ * @param slotList The [List] of equipment slot [String] to be parsed.
+ *
+ * @return The parsed [Set] of [EquipmentSlot].
+ *
+ * @throws IllegalArgumentException when the list is `null` or contains null elements.
+ * @throws InvalidConfigurationException when the list contains invalid EquipmentSlot.
+ */
+ fun parseEquipmentSlots(slotList: List): Set {
+ Validate.noNullElements(slotList)
+
+ return slotList.map {
+ valueOfOrNull(it.uppercase())
+ ?: throw InvalidConfigurationException("Invalid EquipmentSlot value: $it")
+ }.toSet()
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FileUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FileUtils.kt
new file mode 100644
index 00000000..fb70f220
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FileUtils.kt
@@ -0,0 +1,25 @@
+package io.github.slimefunguguproject.bump.utils
+
+import net.guizhanss.guizhanlib.utils.FileUtil
+import java.io.File
+import java.io.IOException
+import java.util.jar.JarEntry
+
+object FileUtils {
+
+ fun listYmlFilesInJar(jarFile: File, folderName: String): List {
+ return try {
+ FileUtil.listJarEntries(
+ jarFile,
+ { entryName: String, entry: JarEntry ->
+ entryName.startsWith("$folderName/") && !entry.isDirectory && entryName.endsWith(".yml")
+ },
+ { entryName: String, _: JarEntry ->
+ entryName.replace("$folderName/", "")
+ }
+ )
+ } catch (e: IOException) {
+ emptyList()
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.kt
new file mode 100644
index 00000000..da053f96
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/FoodLevelUtils.kt
@@ -0,0 +1,51 @@
+package io.github.slimefunguguproject.bump.utils
+
+import org.bukkit.Bukkit
+import org.bukkit.GameMode
+import org.bukkit.entity.Player
+import org.bukkit.event.entity.FoodLevelChangeEvent
+import kotlin.math.min
+
+object FoodLevelUtils {
+
+ /**
+ * This method calls [FoodLevelChangeEvent] and add [Player]'s
+ * food level if [Player]'s [GameMode] is not creative/spectator and
+ * the event is not cancelled
+ *
+ * @param p the [Player] that food level will be changed
+ * @param level the level to be added
+ *
+ * @return if the food level is added
+ */
+ fun add(p: Player, level: Int): Boolean {
+ val newLevel = min(20, p.foodLevel + level)
+ return set(p, newLevel)
+ }
+
+ /**
+ * This method calls [FoodLevelChangeEvent] and set [Player]'s
+ * food level if [Player]'s [GameMode] is not creative/spectator and
+ * the event is not cancelled
+ *
+ * @param p the [Player] that food level will be changed
+ * @param level the target food level
+ *
+ * @return if the food level is changed
+ */
+ fun set(p: Player, level: Int): Boolean {
+ if (p.gameMode == GameMode.CREATIVE || p.gameMode == GameMode.SPECTATOR) {
+ return true
+ }
+
+ val event = FoodLevelChangeEvent(p, level)
+ Bukkit.getPluginManager().callEvent(event)
+
+ return if (!event.isCancelled) {
+ p.foodLevel = event.foodLevel
+ true
+ } else {
+ false
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/GeneralUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/GeneralUtils.kt
new file mode 100644
index 00000000..d30f3f66
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/GeneralUtils.kt
@@ -0,0 +1,79 @@
+package io.github.slimefunguguproject.bump.utils
+
+import io.github.slimefunguguproject.bump.utils.items.ValidateUtils
+import net.guizhanss.guizhanlib.minecraft.utils.MinecraftVersionUtil
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.EnchantmentX
+import net.guizhanss.guizhanlib.utils.StringUtil
+import org.bukkit.Material
+import org.bukkit.inventory.ItemFlag
+import org.bukkit.inventory.ItemStack
+
+object GeneralUtils {
+
+ private const val STAR = "⭐"
+
+ /**
+ * Get a [String] of consecutive stars, maximum at 5.
+ *
+ *
+ * When there are over 5 stars, returns number + star.
+ *
+ * @param n The number of stars
+ *
+ * @return [String] of consecutive stars.
+ */
+ fun getStars(n: Byte): String {
+ return if (n <= 5) {
+ var num = n
+ val builder = StringBuilder()
+ while (num > 0) {
+ builder.append(STAR)
+ num--
+ }
+ builder.toString()
+ } else {
+ "$n $STAR"
+ }
+ }
+
+ /**
+ * Make the [ItemStack] glow.
+ *
+ * @param item The [ItemStack] to be dealt with.
+ */
+ fun glowItem(item: ItemStack) {
+ if (!ValidateUtils.noAirItem(item)) {
+ return
+ }
+
+ val itemMeta = item.itemMeta!!
+ if (MinecraftVersionUtil.isAtLeast(20, 5)) {
+ itemMeta.setEnchantmentGlintOverride(true)
+ } else {
+ itemMeta.addEnchant(EnchantmentX.LUCK_OF_THE_SEA, 1, true)
+ itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS)
+ }
+ item.setItemMeta(itemMeta)
+ }
+
+ /**
+ * Get the [Material] name.
+ *
+ * @param material The [Material].
+ *
+ * @return The material name in Simplified Chinese if GuizhanLibPlugin exists. Otherwise, in English.
+ */
+ fun getMaterialName(material: Material): String {
+ // TODO: Make an adapter for GuizhanLib 2.0 updates
+ try {
+ val clazz = Class.forName("net.guizhanss.guizhanlib.minecraft.helper.MaterialHelper")
+ val result = clazz.getMethod("getName", Material::class.java).invoke(null, material)
+ return result.toString()
+ } catch (e: Exception) {
+ return StringUtil.humanize(material.toString())
+ }
+ }
+
+ inline fun > valueOfOrNull(name: String): T? =
+ enumValues().firstOrNull { it.name == name }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/JsonUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/JsonUtils.kt
new file mode 100644
index 00000000..d05ba308
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/JsonUtils.kt
@@ -0,0 +1,27 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.utils
+
+import com.google.gson.JsonElement
+import com.google.gson.JsonParser
+import com.google.gson.stream.JsonReader
+import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion
+import io.github.thebusybiscuit.slimefun4.implementation.Slimefun
+
+object JsonUtils {
+
+ /**
+ * This method parses JSON from the [JsonReader].
+ *
+ * @param reader The [JsonReader] to be read JSON from.
+ *
+ * @return The root [JsonElement]
+ */
+ fun parseReader(reader: JsonReader): JsonElement {
+ return if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_18)) {
+ JsonParser.parseReader(reader)
+ } else {
+ JsonParser().parse(reader)
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/WikiUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/WikiUtils.kt
new file mode 100644
index 00000000..1bac1365
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/WikiUtils.kt
@@ -0,0 +1,20 @@
+package io.github.slimefunguguproject.bump.utils
+
+import io.github.slimefunguguproject.bump.Bump
+import org.bukkit.plugin.Plugin
+import java.util.logging.Level
+
+object WikiUtils {
+
+ fun setupJson() {
+ try {
+ val clazz = Class.forName("net.guizhanss.slimefun4.utils.WikiUtils")
+ clazz.getMethod("setupJson", Plugin::class.java).invoke(null, Bump.instance)
+ } catch (e: Exception) {
+ Bump.log(
+ Level.WARNING,
+ "Cannot load wiki pages. You can safely ignore this message if you are using Official Slimefun DEV/RC version."
+ )
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Keys.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Keys.kt
new file mode 100644
index 00000000..819cadc1
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Keys.kt
@@ -0,0 +1,17 @@
+package io.github.slimefunguguproject.bump.utils.constant
+
+import io.github.slimefunguguproject.bump.Bump
+import org.bukkit.NamespacedKey
+import java.util.Locale
+
+object Keys {
+
+ val APPRAISABLE = "appraisable".createKey()
+ val APPRAISE_LEVEL = "appraise_level".createKey()
+ val APPRAISE_VERSION = "appraise_version".createKey()
+ val LAST_USED = "last_used".createKey()
+ val HEAVEN_BREAKING_SWORD_PROTECTED = "heaven_breaking_sword_protected".createKey()
+ val PROJECTILE = "projectile".createKey()
+
+ fun String.createKey() = NamespacedKey(Bump.instance, this.lowercase(Locale.getDefault()))
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Patterns.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Patterns.kt
new file mode 100644
index 00000000..067828b5
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Patterns.kt
@@ -0,0 +1,10 @@
+package io.github.slimefunguguproject.bump.utils.constant
+
+import java.util.regex.Pattern
+
+object Patterns {
+
+ val MINECRAFT_NAMESPACEDKEY: Pattern = Pattern.compile("minecraft:[a-z0-9/._-]+")
+ val BUMP_TAG: Pattern = Pattern.compile("#bump:[a-z_]+")
+ val BUMP_TAG_CONFIG: Pattern = Pattern.compile("bump:[a-z_]+")
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Strings.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Strings.kt
new file mode 100644
index 00000000..690efbae
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/constant/Strings.kt
@@ -0,0 +1,14 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.utils.constant
+
+import org.bukkit.ChatColor
+
+object Strings {
+
+ val CHECK = ChatColor.GREEN.toString() + "✔"
+ val CROSS = ChatColor.RED.toString() + "✘"
+
+ const val WIKI_EN = "https://docs.ybw0014.dev/bump/"
+ const val WIKI_CN = "https://slimefun-addons-wiki.guizhanss.cn/bump/"
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/general/RequiredProperty.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/general/RequiredProperty.kt
new file mode 100644
index 00000000..37c7a79d
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/general/RequiredProperty.kt
@@ -0,0 +1,23 @@
+package io.github.slimefunguguproject.bump.utils.general
+
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+
+/**
+ * [RequiredProperty](https://github.com/Slimefun-Addon-Community/Galactifun2/blob/master/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/general/RequiredProperty.kt)
+ * from Slimefun-Addon-Community/Galactifun2
+ */
+class RequiredProperty(
+ private var value: T? = null,
+ private val getter: (T) -> T = { it },
+ private val setter: (T) -> T = { it }
+) : ReadWriteProperty {
+
+ override fun getValue(thisRef: Any, property: KProperty<*>): T {
+ return getter(value ?: error("${property.name} must be set"))
+ }
+
+ override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
+ this.value = setter(value)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/AppraiseUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/AppraiseUtils.kt
new file mode 100644
index 00000000..bc846968
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/AppraiseUtils.kt
@@ -0,0 +1,82 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.utils.items
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.appraise.AppraiseType
+import io.github.slimefunguguproject.bump.utils.constant.Keys
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.AttributeX
+import org.bukkit.ChatColor
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier
+import org.bukkit.inventory.ItemStack
+
+object AppraiseUtils {
+
+ /**
+ * Check if the [ItemStack] is marked as appraisable,
+ * which means it can be used in appraisal instrument.
+ *
+ * @param itemStack The [ItemStack] to be checked.
+ *
+ * @return Whether the [ItemStack] is marked as appraisable.
+ */
+ fun isAppraisable(itemStack: ItemStack?): Boolean {
+ return if (ValidateUtils.noAirItem(itemStack)) {
+ PersistentDataAPI.getBoolean(itemStack!!.itemMeta!!, Keys.APPRAISABLE)
+ } else {
+ false
+ }
+ }
+
+ /**
+ * Set the [ItemStack] as appraisable in appraisal instrument
+ *
+ * @param itemStack the [ItemStack] to be set
+ */
+ fun setAppraisable(itemStack: ItemStack) {
+ if (!ValidateUtils.noAirItem(itemStack)) {
+ return
+ }
+
+ val im = itemStack.itemMeta!!
+
+ // set lore
+ val lore = if (im.hasLore()) im.lore!! else ArrayList()
+ lore.add("")
+ lore.add(ChatUtil.color(Bump.localization.getString("lores.not-appraised")))
+ im.lore = lore
+
+ // set pdc
+ PersistentDataAPI.setBoolean(im, Keys.APPRAISABLE, true)
+
+ itemStack.setItemMeta(im)
+ }
+
+ /**
+ * Check if the [ItemStack] is appraised
+ *
+ * @param itemStack the [ItemStack] to be checked
+ *
+ * @return if the [ItemStack] is appraised
+ */
+ fun isAppraised(itemStack: ItemStack): Boolean {
+ if (!ValidateUtils.noAirItem(itemStack)) {
+ return false
+ }
+ return PersistentDataAPI.hasByte(itemStack.itemMeta!!, Keys.APPRAISE_LEVEL)
+ }
+
+ fun getOperation(attribute: Attribute): AttributeModifier.Operation {
+ return when (attribute) {
+ Attribute.GENERIC_MOVEMENT_SPEED, AttributeX.GENERIC_JUMP_STRENGTH -> AttributeModifier.Operation.ADD_SCALAR
+ else -> AttributeModifier.Operation.ADD_NUMBER
+ }
+ }
+
+ fun getDescriptionLore(type: AppraiseType) = type.description
+ .map { ChatUtil.color("${ChatColor.GRAY}${it}") }
+ .toMutableList()
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/DisplayItemBuilder.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/DisplayItemBuilder.kt
new file mode 100644
index 00000000..cac5d9a5
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/DisplayItemBuilder.kt
@@ -0,0 +1,36 @@
+@file:Suppress("deprecation")
+
+package io.github.slimefunguguproject.bump.utils.items
+
+import io.github.slimefunguguproject.bump.utils.general.RequiredProperty
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import net.guizhanss.guizhanlib.minecraft.utils.compatibility.ItemFlagX
+import org.bukkit.inventory.ItemFlag
+import org.bukkit.inventory.ItemStack
+
+class DisplayItemBuilder {
+
+ var material: MaterialType by RequiredProperty()
+ var name: String by RequiredProperty()
+ var lore: List by RequiredProperty()
+
+ var postCreate: (ItemStack) -> Unit = {}
+
+ fun build(): ItemStack {
+ val item = material.convert()
+ val meta = item.itemMeta!!
+ meta.setDisplayName(ChatUtil.color(name))
+ meta.lore = lore.map { ChatUtil.color(it) }
+ meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlagX.HIDE_ADDITIONAL_TOOLTIP, ItemFlag.HIDE_ENCHANTS)
+ item.itemMeta = meta
+ postCreate(item)
+ return item
+ }
+}
+
+inline fun buildDisplayItem(
+ builder: DisplayItemBuilder.() -> Unit
+): ItemStack {
+ return DisplayItemBuilder().apply(builder).build()
+}
+
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/MaterialType.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/MaterialType.kt
new file mode 100644
index 00000000..4359b0a9
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/MaterialType.kt
@@ -0,0 +1,25 @@
+package io.github.slimefunguguproject.bump.utils.items
+
+import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils
+import org.bukkit.Material as BukkitMaterial
+import org.bukkit.inventory.ItemStack as BukkitItemStack
+
+sealed interface MaterialType {
+
+ fun convert(): BukkitItemStack
+
+ class Material(private val material: BukkitMaterial) : MaterialType {
+
+ override fun convert() = BukkitItemStack(material)
+ }
+
+ class ItemStack(private val itemStack: BukkitItemStack) : MaterialType {
+
+ override fun convert() = itemStack
+ }
+
+ class Head(private val texture: String) : MaterialType {
+
+ override fun convert() = SlimefunUtils.getCustomHead(texture)
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/RecipeUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/RecipeUtils.kt
new file mode 100644
index 00000000..b190c2c3
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/RecipeUtils.kt
@@ -0,0 +1,8 @@
+package io.github.slimefunguguproject.bump.utils.items
+
+import org.bukkit.inventory.ItemStack
+
+object RecipeUtils {
+
+ fun centerRecipe(item: ItemStack) = arrayOf(null, null, null, null, item, null, null, null, null)
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/SlimefunItemBuilder.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/SlimefunItemBuilder.kt
new file mode 100644
index 00000000..d7fbbbba
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/SlimefunItemBuilder.kt
@@ -0,0 +1,63 @@
+package io.github.slimefunguguproject.bump.utils.items
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.utils.general.RequiredProperty
+import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
+import net.guizhanss.guizhanlib.minecraft.utils.ChatUtil
+import org.bukkit.Material
+import org.bukkit.inventory.ItemStack
+import java.util.logging.Level
+import kotlin.reflect.KClass
+import kotlin.reflect.full.primaryConstructor
+
+/**
+ * Modified from [ItemBuilder](https://github.com/Slimefun-Addon-Community/Galactifun2/blob/master/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/items/SlimefunItemBuilder.kt)
+ * in project Slimefun-Addon-Community/Galactifun2
+ */
+class SlimefunItemBuilder {
+
+ var id: String by RequiredProperty()
+ var material: MaterialType by RequiredProperty()
+
+ var itemGroup: ItemGroup by RequiredProperty()
+ var recipeType: RecipeType by RequiredProperty()
+ var recipe: Array by RequiredProperty()
+
+ var postCreate: (SlimefunItemStack) -> Unit = {}
+
+ private val extraLore = mutableListOf()
+
+ operator fun String.unaryPlus() {
+ extraLore += ChatUtil.color(this)
+ }
+
+ fun build(clazz: KClass, vararg otherArgs: Any?): SlimefunItemStack {
+ val name = Bump.localization.getItemName(id)
+ val lore = Bump.localization.getItemLore(id).toMutableList() + extraLore
+ val sfItem = SlimefunItemStack(
+ "${Bump.localization.idPrefix}$id",
+ material.convert(),
+ name,
+ *lore.toTypedArray()
+ )
+ postCreate(sfItem)
+ val constructor = clazz.primaryConstructor ?: error("Primary constructor not found for $clazz")
+ constructor.call(itemGroup, sfItem, recipeType, recipe, *otherArgs).register(Bump.instance)
+ return sfItem
+ }
+}
+
+inline fun buildSlimefunItem(
+ vararg otherArgs: Any?,
+ builder: SlimefunItemBuilder.() -> Unit
+): SlimefunItemStack {
+ try {
+ return SlimefunItemBuilder().apply(builder).build(I::class, *otherArgs)
+ } catch (e: Exception) {
+ Bump.log(Level.SEVERE, e, "Failed to build Slimefun item")
+ return SlimefunItemStack("ERROR", ItemStack(Material.AIR))
+ }
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/ValidateUtils.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/ValidateUtils.kt
new file mode 100644
index 00000000..99b11c80
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/items/ValidateUtils.kt
@@ -0,0 +1,24 @@
+package io.github.slimefunguguproject.bump.utils.items
+
+import org.bukkit.inventory.ItemStack
+
+object ValidateUtils {
+
+ /**
+ * Validate the given [ItemStack] is not `null` or an air item.
+ *
+ * @param itemStack The [ItemStack] to be validated.
+ *
+ * @return if the [ItemStack] is valid.
+ */
+ fun noAirItem(itemStack: ItemStack?) = itemStack != null && !itemStack.type.isAir
+
+ /**
+ * Validate the given [ItemStack] is not `null`, not an air item, and has item meta.
+ *
+ * @param itemStack The [ItemStack] to be validated.
+ *
+ * @return if the [ItemStack] is valid.
+ */
+ fun noAirAndHasItemMeta(itemStack: ItemStack?) = noAirItem(itemStack) && itemStack!!.hasItemMeta()
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/BumpTag.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/BumpTag.kt
new file mode 100644
index 00000000..93366ad9
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/BumpTag.kt
@@ -0,0 +1,176 @@
+package io.github.slimefunguguproject.bump.utils.tags
+
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.exceptions.TagMisconfigurationException
+import io.github.slimefunguguproject.bump.utils.constant.Keys.createKey
+import org.bukkit.Material
+import org.bukkit.NamespacedKey
+import org.bukkit.Tag
+import java.util.logging.Level
+
+enum class BumpTag : Tag {
+ /**
+ * This includes all swords.
+ */
+ SWORD,
+
+ /**
+ * This includes all helmets.
+ */
+ HELMET,
+
+ /**
+ * This includes all chestplates.
+ */
+ CHESTPLATE,
+
+ /**
+ * This includes all leggings.
+ */
+ LEGGINGS,
+
+ /**
+ * This includes all boots.
+ */
+ BOOTS,
+
+ /**
+ * This includes all horse armors.
+ */
+ HORSE_ARMOR,
+
+ /**
+ * This includes all axes.
+ */
+ AXE,
+
+ /**
+ * This includes all pickaxes.
+ */
+ PICKAXE,
+
+ /**
+ * This includes all shovels.
+ */
+ SHOVEL,
+
+ /**
+ * This includes all hoes.
+ */
+ HOE,
+
+ /**
+ * This includes all fishing rods.
+ */
+ FISHING_ROD,
+
+ /**
+ * This includes all bows.
+ */
+ BOW,
+
+ /**
+ * This includes all kinds of heads.
+ */
+ HEAD,
+
+ /**
+ * This includes all carpets.
+ */
+ CARPET,
+
+ /**
+ * This includes all materials that is suitable for main hand slot.
+ */
+ HAND_SLOT,
+
+ /**
+ * This includes all materials that is suitable for off hand slot.
+ */
+ OFF_HAND_SLOT,
+
+ /**
+ * This includes all materials that is suitable for head slot.
+ */
+ HEAD_SLOT,
+
+ /**
+ * This includes all materials that is suitable for chest slot.
+ */
+ CHEST_SLOT,
+
+ /**
+ * This includes all materials that is suitable for legs slot.
+ */
+ LEGS_SLOT,
+
+ /**
+ * This includes all materials that is suitable for feet slot.
+ */
+ FEET_SLOT;
+
+ private var key: NamespacedKey = name.createKey()
+ private val materials: MutableSet = HashSet()
+ private val additionalTags: MutableSet> = HashSet()
+
+ init {
+ this.key = name.createKey()
+ }
+
+ companion object {
+
+ /**
+ * Get a tag by the name. null if not found.
+ */
+ fun getTag(name: String) = entries.firstOrNull { it.name == name }
+
+ /**
+ * Reload all tags.
+ */
+ fun reloadAll() {
+ for (tag in entries) {
+ tag.reload()
+ }
+ }
+ }
+
+ /**
+ * Reload this [BumpTag] from resources.
+ */
+ fun reload() {
+ try {
+ TagParser(this).parse { materialSet: Set, additionalTagSet: Set> ->
+ materials.clear()
+ materials.addAll(materialSet)
+
+ additionalTags.clear()
+ additionalTags.addAll(additionalTagSet)
+ }
+ } catch (ex: TagMisconfigurationException) {
+ Bump.log(
+ Level.SEVERE, ex,
+ "An error has occurred while trying to load Bump tag: $name"
+ )
+ }
+ }
+
+ override fun getKey() = key
+
+ override fun isTagged(material: Material): Boolean {
+ return if (materials.contains(material)) {
+ true
+ } else {
+ return additionalTags.any { it.isTagged(material) }
+ }
+ }
+
+ override fun getValues(): Set {
+ return if (additionalTags.isEmpty()) {
+ materials.toSet()
+ } else {
+ materials.union(additionalTags.flatMap { it.values }).toSet()
+ }
+ }
+
+ fun isEmpty() = materials.isEmpty() && values.isEmpty()
+}
diff --git a/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/TagParser.kt b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/TagParser.kt
new file mode 100644
index 00000000..3ed9dd48
--- /dev/null
+++ b/src/main/kotlin/io/github/slimefunguguproject/bump/utils/tags/TagParser.kt
@@ -0,0 +1,94 @@
+package io.github.slimefunguguproject.bump.utils.tags
+
+import com.google.gson.JsonArray
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import com.google.gson.stream.JsonReader
+import io.github.slimefunguguproject.bump.Bump
+import io.github.slimefunguguproject.bump.api.exceptions.TagMisconfigurationException
+import io.github.slimefunguguproject.bump.utils.JsonUtils
+import io.github.slimefunguguproject.bump.utils.constant.Patterns
+import io.github.thebusybiscuit.slimefun4.libraries.dough.common.CommonPatterns
+import org.bukkit.Keyed
+import org.bukkit.Material
+import org.bukkit.NamespacedKey
+import org.bukkit.Tag
+import java.io.InputStreamReader
+import java.nio.charset.StandardCharsets
+import java.util.function.BiConsumer
+
+/**
+ * The [TagParser] is responsible for parsing a JSON file into a [BumpTag].
+ *
+ * @author ybw0014
+ * @see BumpTag
+ */
+internal class TagParser(tag: BumpTag) : Keyed {
+
+ /**
+ * Every [Tag] has a [NamespacedKey].
+ * This is the [NamespacedKey] for the resulting [Tag].
+ */
+ private val tagKey = tag.key
+
+ /**
+ * This will parse the JSON and run the provided callback with [Sets][Set] of
+ * matched [Materials][Material] and [Tags][Tag].
+ *
+ * @param callback A callback to run after successfully parsing the input.
+ *
+ * @throws TagMisconfigurationException This is thrown whenever the given input is malformed or no adequate
+ * [Material] or [Tag] could be found
+ */
+ fun parse(callback: BiConsumer, Set>>) {
+ val path = "/tags/" + key.key + ".json"
+ val materials: MutableSet = mutableSetOf()
+ val tags: MutableSet> = mutableSetOf()
+
+ try {
+ val stream = Bump::class.java.getResourceAsStream(path) ?: error("Tag file not found within jar: $path")
+ val reader = JsonReader(InputStreamReader(stream, StandardCharsets.UTF_8))
+ val root: JsonObject = JsonUtils.parseReader(reader).asJsonObject
+ val child = root["values"]
+
+ if (child !is JsonArray) {
+ error("No values array specified")
+ }
+
+ val values = child.asJsonArray
+
+ for (element in values) {
+ if (element is JsonPrimitive && element.isString) {
+ parseString(element.asString, materials, tags)
+ } else {
+ error("Unexpected value format: " + element.javaClass.simpleName + " - " + element)
+ }
+ }
+
+ callback.accept(materials, tags)
+ } catch (ex: Exception) {
+ throw TagMisconfigurationException(key, ex)
+ }
+ }
+
+ private fun parseString(value: String, materials: MutableSet, tags: MutableSet>) {
+ if (Patterns.MINECRAFT_NAMESPACEDKEY.matcher(value).matches()) {
+ val material = Material.matchMaterial(value)
+
+ if (material != null) {
+ materials.add(material)
+ }
+ } else if (Patterns.BUMP_TAG.matcher(value).matches()) {
+ val keyValue = CommonPatterns.COLON.split(value)[1].uppercase()
+ val tag = BumpTag.getTag(keyValue)
+
+ if (tag != null) {
+ tags.add(tag)
+ } else {
+ error("Bump tag not exist: $keyValue")
+ }
+ }
+ }
+
+ override fun getKey() = tagKey
+}
diff --git a/src/main/resources/appraise-types.yml b/src/main/resources/appraise-types.yml
deleted file mode 100644
index db140260..00000000
--- a/src/main/resources/appraise-types.yml
+++ /dev/null
@@ -1,117 +0,0 @@
-# Refer to our wiki to learn more:
-sword:
- enabled: true
- name: "Sword"
- description:
- - "Any Slimefun sword."
- equipment-type: SLIMEFUN
- check-material: true
- materials:
- - bump:sword
- equipment-slots:
- - HAND
- attributes:
- GENERIC_ATTACK_DAMAGE:
- min: 0
- max: 30
- weight: 40
- GENERIC_ATTACK_SPEED:
- min: -3
- max: 10
- weight: 25
- GENERIC_MOVEMENT_SPEED:
- min: -0.4
- max: 0.6
- weight: 15
- GENERIC_LUCK:
- min: -3
- max: 10
- weight: 10
- GENERIC_ATTACK_KNOCKBACK:
- min: -2
- max: 12
- weight: 10
-
-armor:
- enabled: true
- name: "Armor"
- description:
- - "Any Slimefun armor."
- equipment-type: SLIMEFUN
- check-material: true
- materials:
- - bump:helmet
- - bump:chestplate
- - bump:leggings
- - bump:boots
- equipment-slots:
- - HEAD
- - CHEST
- - LEGS
- - FEET
- attributes:
- GENERIC_ARMOR:
- min: 0
- max: 30
- weight: 40
- GENERIC_ARMOR_TOUGHNESS:
- min: -2
- max: 12
- weight: 25
- GENERIC_MAX_HEALTH:
- min: -5
- max: 12
- weight: 15
- GENERIC_KNOCKBACK_RESISTANCE:
- min: -0.2
- max: 0.8
- weight: 10
- GENERIC_FLYING_SPEED:
- min: -3
- max: 5
- weight: 7
- ZOMBIE_SPAWN_REINFORCEMENTS:
- min: -5
- max: 5
- weight: 3
-
-horse_armor:
- enabled: true
- name: "Horse Armor"
- description:
- - "Any horse armor."
- equipment-type: ANY
- check-material: true
- materials:
- - bump:horse_armor
- equipment-slots:
- - CHEST
- attributes:
- GENERIC_MAX_HEALTH:
- min: 0
- max: 30
- weight: 30
- GENERIC_ARMOR:
- min: -5
- max: 30
- weight: 15
- GENERIC_ARMOR_TOUGHNESS:
- min: -2
- max: 12
- weight: 10
- GENERIC_KNOCKBACK_RESISTANCE:
- min: -0.2
- max: 0.8
- weight: 5
- HORSE_JUMP_STRENGTH:
- min: -0.5
- max: 1.4
- weight: 20
- GENERIC_MOVEMENT_SPEED:
- min: -0.5
- max: 1.2
- weight: 15
- GENERIC_FOLLOW_RANGE:
- min: -50
- max: 250
- weight: 5
diff --git a/src/main/resources/appraise.yml b/src/main/resources/appraise.yml
new file mode 100644
index 00000000..c1b558fc
--- /dev/null
+++ b/src/main/resources/appraise.yml
@@ -0,0 +1,380 @@
+stars:
+ 100: 20
+ 98: 10
+ 96: 9
+ 92: 8
+ 88: 7
+ 82: 6
+ 74: 5
+ 64: 4
+ 48: 3
+ 30: 2
+ 10: 1
+types:
+# v < 1.20.5
+ sword_v1:
+ enabled: true
+ conditions:
+ - "v < 1.20.5"
+ name: "Sword"
+ description:
+ - "Any Slimefun sword."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:sword
+ equipment-slots:
+ - HAND
+ attributes:
+ GENERIC_ATTACK_DAMAGE:
+ min: 0
+ max: 30
+ weight: 40
+ GENERIC_ATTACK_SPEED:
+ min: -3
+ max: 10
+ weight: 25
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.4
+ max: 0.6
+ weight: 15
+ GENERIC_LUCK:
+ min: -3
+ max: 10
+ weight: 10
+ GENERIC_ATTACK_KNOCKBACK:
+ min: -2
+ max: 12
+ weight: 10
+
+ armor_v1:
+ enabled: true
+ conditions:
+ - "v < 1.20.5"
+ name: "Armor"
+ description:
+ - "Any Slimefun armor."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:helmet
+ - bump:chestplate
+ - bump:leggings
+ - bump:boots
+ equipment-slots:
+ - HEAD
+ - CHEST
+ - LEGS
+ - FEET
+ attributes:
+ GENERIC_ARMOR:
+ min: 0
+ max: 30
+ weight: 40
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 12
+ weight: 25
+ GENERIC_MAX_HEALTH:
+ min: -5
+ max: 12
+ weight: 20
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.8
+ weight: 15
+
+ horse_armor_v1:
+ enabled: true
+ conditions:
+ - "v < 1.20.5"
+ name: "Horse Armor"
+ description:
+ - "Any horse armor."
+ equipment-type: ANY
+ check-material: true
+ materials:
+ - bump:horse_armor
+ equipment-slots:
+ - CHEST
+ attributes:
+ GENERIC_MAX_HEALTH:
+ min: 0
+ max: 30
+ weight: 30
+ GENERIC_ARMOR:
+ min: -5
+ max: 30
+ weight: 15
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 12
+ weight: 10
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.8
+ weight: 10
+ HORSE_JUMP_STRENGTH:
+ min: -0.5
+ max: 1.4
+ weight: 20
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.5
+ max: 1.2
+ weight: 15
+
+# 1.20.5 <= v < 1.21
+
+ helmet_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Helmet"
+ description:
+ - "Any Slimefun helmet."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:head_slot
+ equipment-slots:
+ - HEAD
+ attributes:
+ GENERIC_ARMOR:
+ min: 0
+ max: 10
+ weight: 40
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 5
+ weight: 20
+ GENERIC_MAX_HEALTH:
+ min: -2
+ max: 6
+ weight: 20
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.4
+ weight: 10
+ GENERIC_FOLLOW_RANGE:
+ min: -25
+ max: 100
+ weight: 10
+ chestplate_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Chestplate"
+ description:
+ - "Any Slimefun chestplate."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:chest_slot
+ equipment-slots:
+ - CHEST
+ attributes:
+ GENERIC_ARMOR:
+ min: 0
+ max: 10
+ weight: 40
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 5
+ weight: 20
+ GENERIC_MAX_HEALTH:
+ min: -2
+ max: 6
+ weight: 20
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.4
+ weight: 20
+ leggings_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Leggings"
+ description:
+ - "Any Slimefun leggings."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:legs_slot
+ equipment-slots:
+ - LEGS
+ attributes:
+ GENERIC_ARMOR:
+ min: 0
+ max: 10
+ weight: 40
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 5
+ weight: 20
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.4
+ weight: 20
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.1
+ max: 0.5
+ weight: 10
+ GENERIC_JUMP_STRENGTH:
+ min: -2
+ max: 6
+ weight: 10
+ boots_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Boots"
+ description:
+ - "Any Slimefun boots."
+ equipment-type: SLIMEFUN
+ check-material: true
+ materials:
+ - bump:feet_slot
+ equipment-slots:
+ - FEET
+ attributes:
+ GENERIC_ARMOR:
+ min: 0
+ max: 30
+ weight: 40
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 12
+ weight: 25
+ GENERIC_MAX_HEALTH:
+ min: -5
+ max: 12
+ weight: 15
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.8
+ weight: 10
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.1
+ max: 0.6
+ weight: 5
+ ENERIC_STEP_HEIGHT:
+ min: 0.6
+ max: 3
+ weight: 15
+ off_hand_slot_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "OFF HAND SLOT"
+ description:
+ - "Any off hand tools."
+ equipment-type: ANY
+ check-material: true
+ materials:
+ - bump:off_hand_slot
+ equipment-slots:
+ - OFF_HAND
+ attributes:
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 12
+ weight: 30
+ GENERIC_MAX_HEALTH:
+ min: -5
+ max: 12
+ weight: 20
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.8
+ weight: 15
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.1
+ max: 0.6
+ weight: 15
+ GENERIC.MAX_ABSORPTION:
+ min: 4
+ max: 8
+ weight: 20
+ hand_slot_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Boots"
+ description:
+ - "Any tools or swords."
+ equipment-type: ANY
+ check-material: true
+ materials:
+ - bump:hand_slot
+ equipment-slots:
+ - HAND
+ attributes:
+ GENERIC_ATTACK_SPEED:
+ min: 0.2
+ max: 1
+ weight: 15
+ GENERIC_ENTITY_INTERACTION_RANGE:
+ min: 1
+ max: 10
+ weight: 15
+ GENERIC_ATTACK_DAMAGE:
+ min: 10
+ max: 25
+ weight: 15
+ GENERIC_BLOCK_INTERACTION_RANGE:
+ min: 4.5
+ max: 12
+ weight: 45
+ GENERIC_ATTACK_KNOCKBACK:
+ min: 4
+ max: 8
+ weight: 10
+ mob_armor_v2:
+ enabled: true
+ conditions:
+ - "v >= 1.20.5"
+ - "v < 1.21"
+ name: "Boots"
+ description:
+ - "Any horse/wolf armors and carpets/saddles."
+ equipment-type: ANY
+ check-material: true
+ materials:
+ - bump:mob_armor
+ equipment-slots:
+ - CHEST
+ attributes:
+ GENERIC_MAX_HEALTH:
+ min: 0
+ max: 30
+ weight: 30
+ GENERIC_ARMOR:
+ min: -5
+ max: 30
+ weight: 10
+ GENERIC_ARMOR_TOUGHNESS:
+ min: -2
+ max: 12
+ weight: 10
+ GENERIC_KNOCKBACK_RESISTANCE:
+ min: -0.2
+ max: 0.8
+ weight: 10
+ GENERIC_JUMP_STRENGTH:
+ min: -0.5
+ max: 1.4
+ weight: 20
+ GENERIC_MOVEMENT_SPEED:
+ min: -0.5
+ max: 1.2
+ weight: 10
+ GENERIC_ATTACK_DAMAGE:
+ min: 5.5
+ max: 18
+ weight: 10
\ No newline at end of file
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index d816af2e..86cd9926 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,31 +1,24 @@
-# DO NOT modify this
-version: 4
+# Auto update
+auto-update: true
-options:
- # Auto update
- auto-update: true
- # Bump language (Available languages: https://github.com/SlimefunGuguProject/Bump#supported-languages)
- lang: en-US
- # Enable researches
- enable-researches: true
+# Enable debug logs
+debug: false
+# Default Bump language (Available languages: https://github.com/SlimefunGuguProject/Bump#supported-languages)
+# SlimefunTranslation is supported
+lang: en
+
+# Enable researches
+enable-researches: true
+
+# Weapon settings
weapons:
# The duration of projectiles launched by any Bump weapon (in Slimefun ticks)
projectile-duration: 10
-# Appraise system
-appraise:
- # The thresholds of stars (appraise result levels).
- # The star is determined by the calculation of overall appraise result.
- stars:
- 100: 20
- 98: 10
- 96: 9
- 92: 8
- 88: 7
- 82: 6
- 74: 5
- 64: 4
- 48: 3
- 30: 2
- 10: 1
+appraiser:
+ # Broadcast the appraisal result to the whole server
+ broadcast:
+ enabled: true
+ # The required number of stars to broadcast the appraisal result to everyone
+ star-requirement: 7
diff --git a/src/main/resources/lang/bg-BG.yml b/src/main/resources/lang/bg-BG.yml
deleted file mode 100644
index abab0de6..00000000
--- a/src/main/resources/lang/bg-BG.yml
+++ /dev/null
@@ -1,308 +0,0 @@
----
-categories:
- main: "&bУдар"
- armor: "&bУдар - Брони"
- food: "&bУдар - Храни"
- machine: "&bУдар - Машини"
- stuff: "&bУдар - Неща"
- tool: "&bУдар - Инструменти"
- weapon: "&bУдар - Магически оръжия"
-items:
- random_helmet:
- name: "&6Случаен шлем"
- lore:
- - ""
- - "&b&k|&b- &7&oКак е късметът ми..."
- - "&b&k|&b- &e&oОценителят &7&oслучайно дава атрибутът..."
- random_horse_armor:
- name: "&6Случайна конска броня"
- lore:
- - ""
- - "&b&k|&b- &7&oКак е късметът ми..."
- - "&b&k|&b- &e&oОценителят &7&oслучайно дава атрибутът..."
- xuebi:
- name: "&6Спрайт"
- lore:
- - ""
- - "&b&k|&b- Много сладко и сладко, продължава да бълбука!"
- - ""
- kele:
- name: "&eКола"
- lore:
- - ""
- - "&b&k|&b- Ледът е здрав и ако я изпиеш, може да полетиш!"
- - ""
- fangbianmian:
- name: "&eЮфката за спешни случаи на майстор Конг"
- lore:
- - ""
- - "&b&k|&b- Този вкус е пикантен!!"
- - ""
- latiao:
- name: "&eПикантен глутен"
- lore:
- - ""
- - "&b&k|&b- Яко! Продължавам да не забравям да оближа пикантното масло след ядене..."
- - ""
- kouxiangtang:
- name: "&eДъвка"
- lore:
- - ""
- - "&b&k|&b- Много лепкаво..."
- - ""
- zongzi:
- name: "&aЗонгзи"
- lore:
- - ""
- - "&b&k|&b- Честит празник на драконовата лодка!"
- - ""
- appraisal:
- name: "&bИнструмент за оценка"
- lore:
- - ""
- - "&c&k|&7- Ох! Дефектен инструмент..."
- - ""
- attribute_grindstone:
- name: "&bАтрибут точило"
- lore:
- - ""
- - "&c&k|&7- Възможно ли е да се махнат атрибутите..."
- - ""
- sun_energy:
- name: "&eФотосинтетична енергия"
- lore:
- - ""
- - "&b&k|&b- Мутиралите растения също ще фотосинтезират..."
- - ""
- mecha_gear:
- name: "&eМеханично зъбно колело"
- lore:
- - ""
- - "&b&k|&b- Нещо е заличено от голяма фабрика..."
- - ""
- old_coin:
- name: "&eСчупена златна монета"
- lore:
- - ""
- - "&b&k|&b- Какво мога да купя..."
- - ""
- make:
- name: "&eКомпютърно ядро"
- lore:
- - ""
- - "&b&k|&b- За какво се използва това..."
- - ""
- old_cpu:
- name: "&eСчупен централен процесор"
- lore:
- - ""
- - "&b&k|&b- От кой компютър е било премахнато..."
- - ""
- cpu:
- name: "&eЦентрален процесор"
- lore:
- - ""
- - "&b&k|&b- Непокътнат..."
- - ""
- soul_paper:
- name: "&eДушевен талисман"
- lore:
- - ""
- - "&b&k|&b- Силата на душата"
- - ""
- ksf_stuff:
- name: "&eПодправка за юфка за спешни случаи"
- lore:
- - ""
- - "&b&k|&b- Църкане~ Пикантно е"
- - ""
- water_sugar:
- name: "&eБонбонена сода"
- lore:
- - ""
- - "&b&k|&b- Спрайт? Или Кока-Кола?"
- - ""
- peach_wood:
- name: "&eПрасковено дърво"
- lore:
- - ""
- - "&b&k|&b- Убежище от зли духове"
- - ""
- update_power:
- name: "&eПодобрено ядро"
- lore:
- - ""
- - "&b&k|&b- Използва се да подобри някои странни предмети..."
- - ""
- getgold_spade:
- name: "&eВземане на златна лопата"
- lore:
- - ""
- - "&b&k|&b- Има определен шанс да изкопаеш златни монети в пясъка!"
- - ""
- appraisal_paper_armor:
- name: "&eПоказател на качеството на броните"
- lore:
- - ""
- - "&b&k|&b- Случаен атрибут на броня за дадения предмет!"
- - "&b&k|&b- Много скъпо, но си заслужава да го запазиш..."
- - ""
- appraisal_paper_damage:
- name: "&eПоказател на качеството на оръжият"
- lore:
- - ""
- - "&b&k|&b- Слачен атрибут за атака за дадения предмет!"
- - "&b&k|&b- Много скъпо, но си заслужава да го запазиш..."
- - ""
- appraisal_paper_horse_armor:
- name: "&eПоказател на качеството на конските брони"
- lore:
- - ""
- - "&b&k|&b- Случаен атрибут на броня за дадения предмет!"
- - "&b&k|&b- Много скъпо, но си заслужава да го запазиш..."
- - ""
- light_bow:
- name: "&6Божият наказващ лък"
- lore:
- - ""
- - "&b&k|&b- &7&oПриеми Божието наказание..."
- - ""
- witherskull_bow:
- name: "&6Уидъров лък"
- lore:
- - ""
- - "&b&k|&b- &7&oКакво започва всеки нежив..."
- - ""
- emer_sword:
- name: "&6Смарагдов меч"
- lore:
- - ""
- - "&b&k|&b- &7&oНаправен от скъпи смарагди..."
- - ""
- bone_sword:
- name: "&6Костен меч"
- lore:
- - ""
- - "&b&k|&b- &7&oМного трудно..."
- - ""
- random_sword:
- name: "&6Случаен къс ръб"
- lore:
- - ""
- - "&b&k|&b- &7&oКак е късметът ми..."
- - "&b&k|&b- &e&oОценителят &7&oслучайно дава атрибутът..."
- guard_sword:
- name: "&6Меч на пазителя"
- lore:
- - ""
- - "&b&k|&b- &7&oЩе те пазя до последния миг от живота ми"
- - ""
- peach_sword:
- name: "&6Меч от прасковено дърво"
- lore:
- - ""
- - "&b&k|&b- &7&oПочит към класическите филми за зомбита..."
- - ""
- soul_sword:
- name: "&Меч на душите"
- lore:
- - ""
- - "&b&k|&b- &7&oДушата на дявола е инжерктирана тук..."
- - "&b&k|&b- &e&oНатиснете с десен бутон, &7&oза да намаите ръмженето..."
- - "&b&k|&b- &7&oПревърни &7&oтвоята &e&oситост &7&oв &e&oздраве &7&o..."
- - ""
- sky_sword:
- name: "&6Меч на небесния разбивач"
- lore:
- - ""
- - "&b&k|&b- &7&oНебесен разрушител, какво властно име..."
- - "&b&k|&b- &e&oНатиснете с десен бутон &7&oи разбийте небето..."
- - ""
- devil_sword:
- name: "&6Меч за убиване на демони"
- lore:
- - ""
- - "&b&k|&b- &7&oУбиецът на демони, какво могъщо име..."
- - "&b&k|&b- &e&oНатиснете с десен бутон &7&oда изпратите свещения огън да помете всичката тъмнина..."
- - ""
- sky_devil_sword:
- name: "&6Разрушаващият меч на небесния демон"
- lore:
- - ""
- - "&b&k|&b- &7&oРазбий облаците и разрежи дявола, един след друг излъчва мощна енергия..."
- - ""
- - ""
-lores:
- per-use: "&7използва се"
- not-appraised: "&b&k|&b- &7&oТова не е оценено"
- appraised: "&b&k|&b- &7&oОцененено &b| &dНиво: &e&|{0}"
-researches:
- food: "Ударна храна"
- random_equipment: "Случайна екипировка"
- appraise: "Оценено"
- stuff: "Магически неща"
- old_stuff: "Вземане на злато"
- bow: "Ударни лъкове"
- peach_sword: "Прасковен меч"
- normal_sword: "Нормален меч"
- soul_sword: "Меч на душите"
- sky_devil: "Небе или демон"
-messages:
- no-input: "&cМоля, поставете предметите тук!"
- output-no-space: "&cНяма изходно място!"
- not-enough-power: "&cНяма достатъчно енергия."
- stacked: "&cНе можете да използвате този предмет, когато е събран с други."
- food:
- cooldown: "&b&k|&b- &7&oТряба да изчакате за малко преди изядете това отново!"
- xuebi: "&b&k|&b- &7&oГотино лято!!"
- kele: "&b&k|&b- &7&oПобедата на дебелия отаку!"
- fangbianmian: "&b&k|&b- &7&oВкусът на детството!"
- latiao: "&b&k|&b- &7&oТова е достатъчно пикантно!"
- kouxiangtang: "&b&k|&b- &7&oПриказен дух пърха!"
- zongzi: "&b&k|&b- &7&oСладко или пикантно?"
- tool:
- getgold_spade: "&b&k|&b- &7&oОБМ, злато..."
- appraisal_paper:
- invalid: "&cТози предмет не е оценим!"
- success: "&aТози предмет може да бъде оценен сега!"
- weapon:
- unavailable: "&b&k|&b- &7&oНе можете да активирате това умение сега!"
- low-food-level: "&b&k|&b- &7&oВашето хранително ниво не е достатъчно, за да промени здравето Ви!"
- cooldown: "&b&k|&b- &7&oТрябва да изчакате малко преди да използвате това оръжие отново!"
- soul_sword:
- converted-part: "&b&k|&b- &7&oЧаст от Вашето хранително ниво е променила здравето ви!"
- converted-all: "&b&k|&b- &7&oЦялото ви хранително ниво е променило здравето Ви!"
- devil_sword: "&b&k|&b- &7&oУбиец на демони, донеси справедливост от небето!"
- sky_sword:
- activated: "&b&k|&b- &7&Небесен разбивач, извиси се в небето!"
- protected: "&b&k|&b- &7&oМечът на небесния разбивач те защити от щети при падането!"
- sky_devil_sword:
- activated: "&b&k|&b- &7&oУбиец на демони или Небесен разрушител, само справедливостта!"
- deactivated: "&b&k|&b- &7&oВремето за подсилване свърши!"
- light_bow: "&b&k|&b- &7&oБог наказва!"
- wither_skull_bow: "&b&k|&b- &7&oЗагиване!"
- machine:
- appraisal:
- invalid: "&cПредметът не може да бъде оценен!"
- appraised: "&cСъжалявам, този предмет не може да бъде разпознат оли вече е оценен!"
- success: "&aОценка!"
- attribute-grindstone:
- invalid: "&cТози предмет не е оценен все още."
- success: "&aОцененият резултат е изтрит!"
-gui:
- appraise:
- name: "&eНатисни за оценяване"
- lore:
- - "&7<- Постави предметите да бъдат оценени отляво"
- - "&7Натисни тук за оценяване"
- appraisal_paper:
- name: "&eНатисни да приложиш"
- lore:
- - "&7<- Постави предметите отляво"
- - "&7Натисни тук, за да позволиш предметът да бъде оценен"
- grind:
- name: "&eНатисни, за да изтриеш атрибутите"
- lore:
- - "&7<- Постави оценение предмети отляво"
- - "&7Натисни тук, за да изтриеш атрибутите"
-
diff --git a/src/main/resources/lang/de-DE.yml b/src/main/resources/lang/de-DE.yml
deleted file mode 100644
index ecd6d8ea..00000000
--- a/src/main/resources/lang/de-DE.yml
+++ /dev/null
@@ -1,270 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Rüstung"
- food: "&bBump - Essen"
- machine: "&bBump - Maschine"
- stuff: "&bBump - Mitarbeiter"
- tool: "&bBump - Werkzeug"
- weapon: "&bBump - Magische Waffe"
- appraise_info: "&eBump - Bewerte Informationen"
- wiki: "&eBump - Wiki"
-items:
- random_helmet:
- name: "&6zufälliger Helm"
- lore:
- - ""
- - "&b&k|&b- &7&oMal sehen, wie viel Glück ich habe..."
- - "&b&k|&b- &e&oDer Appraiser &7&ogibt zufällig dieses Attribut..."
- random_horse_armor:
- name: "&6Zufällige Pferd Rüstung"
- lore:
- - ""
- - "&b&k|&b- &7&oMal sehen, wie viel Glück ich habe..."
- - "&b&k|&b- &e&oDer Appraiser &7&ogibt zufällig dieses Attribut..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&k|&b- Sehr süß und süß, immer noch sprudelnd!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- Das Eis ist voller Kraft, und wenn du es trinkst, dann kannst du fliegen!"
- - ""
- fangbianmian:
- name: "&eMaster Kong Instand-Nudeln"
- lore:
- - ""
- - "&b&k|&b- Das schmeckt sehr scharf!!"
- - ""
- latiao:
- name: "&eWürziges Gluten"
- lore:
- - ""
- - "&b&k|&b- Cool! Ich vergesse immer noch nicht, nach dem Essen das scharfe Öl abzulecken..."
- - ""
- kouxiangtang:
- name: "&eKaugummi"
- lore:
- - ""
- - "&b&k|&b- Sehr klebrig..."
- - ""
- zongzi:
- name: "&aZongzi"
- lore:
- - ""
- - "&b&k|&b- Frohes Drachenboot Festival!"
- - ""
- appraisal:
- name: "&bBewertungsinstrument"
- lore:
- - ""
- - "&c&k|&7- Oh! Ein defektes Instrument..."
- - ""
- attribute_grindstone:
- name: "&bAttribut Schleifstein"
- lore:
- - ""
- - "&c&k|&7- Es ist in der Lage, Attribute zu bereinigen..."
- - ""
- sun_energy:
- name: "&ePhotosynthetische Energie"
- lore:
- - ""
- - "&b&k|&b- Mutierte Pflanzen werden auch Photosynthese betreiben..."
- - ""
- mecha_gear:
- name: "&eMechanisches Getriebe"
- lore:
- - ""
- - "&b&k|&b- Etwas, was von einer großen Fabrik beseitigt wurde..."
- - ""
- old_coin:
- name: "&eKaputte Goldmünze"
- lore:
- - ""
- - "&b&k|&b- Was kann ich kaufen..."
- - ""
- make:
- name: "&eComputer Technologiekern"
- lore:
- - ""
- - "&b&k|&b- Für was wird es verwendet..."
- - ""
- old_cpu:
- name: "&eKaputte CPU"
- lore:
- - ""
- - "&b&k|&b- Von welchem Computer wurde es entfernt..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- Interagieren..."
- - ""
- soul_paper:
- name: "&eSeelentalisman"
- lore:
- - ""
- - "&b&k|&b- Die Kraft der Seele"
- - ""
- ksf_stuff:
- name: "&eInstant-Nudel Gewürz"
- lore:
- - ""
- - "&b&k|&b- Zischen~ Es ist scharf"
- - ""
- water_sugar:
- name: "&eSoda-Süßigkeiten"
- lore:
- - ""
- - "&b&k|&b- Sprite? Oder Coca-Cola?"
- - ""
- peach_wood:
- name: "&ePfirsichholz"
- lore:
- - ""
- - "&b&k|&b- Zuflucht vor bösen Geistern"
- - ""
- update_power:
- name: "&eKern Aufrüsten"
- lore:
- - ""
- - "&b&k|&b- Wird verwendet, um einige seltsame Gegenstände zu verbessern..."
- - ""
- getgold_spade:
- name: "&eBekomme-Gold Schaufel"
- lore:
- - ""
- - "&b&k|&b- Es besteht eine gewisse Chance, zerbrochene Goldmünzen im Sand auszugraben!"
- - ""
- quality_identifier:
- name: "&eQualitäts Identifizierer"
- lore:
- - ""
- - "&b&k|&b- Fügen Sie zufällige Attribute für zufällige Items hinzu!"
- - "&b&k|&b- Sehr teuer, unbedingt behalten..."
- - ""
- appraisal_paper_armor:
- name: "&eRüstungsqualität Identifizierer"
- lore:
- - ""
- - "&b&k|&b- Ein zufälliges Rüstungsattribut für einen bestimmten Gegenstand!"
- - "&b&k|&b- Sehr teuer, unbedingt behalten..."
- - ""
- appraisal_paper_damage:
- name: "&eWaffen-Qualitäts Identifizierer"
- lore:
- - ""
- - "&b&k|&b- Ein zufälliges Attack-Attribut für ein bestimmtes Item!"
- - "&b&k|&b- Sehr teuer, unbedingt behalten..."
- - ""
- appraisal_paper_horse_armor:
- name: "&ePferde Rüstungsqualität-Identifizierer"
- lore:
- - ""
- - "&b&k|&b- Ein zufälliges Rüstungsattribut für einen bestimmten Gegenstand!"
- - "&b&k|&b- Sehr teuer, unbedingt behalten..."
- - ""
- light_bow:
- name: "&6Gott's Bestrafungs Bogen"
- lore:
- - ""
- - "&b&k|&b- &7&oAkzeptiere Gott's Bestrafung..."
- - ""
- witherskull_bow:
- name: "&6Verwelkter Bogen"
- lore:
- - ""
- - "&b&k|&b- &7&oWas es schießt, ist immer untot..."
- - ""
- emer_sword:
- name: "&6Smaragd Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oGemacht aus teuren Smaragden..."
- - ""
- bone_sword:
- name: "&6Knochen Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oSehr hart..."
- - ""
- random_sword:
- name: "&6Zufälliger Short Edge"
- lore:
- - ""
- - "&b&k|&b- &7&oMal sehen, wie viel Glück ich habe..."
- - "&b&k|&b- &e&oDer Appraiser &7&ogibt zufällig dieses Attribut..."
- guard_sword:
- name: "&6Wächter Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oIch werde dich bis auf's lebensende beschützen"
- - ""
- peach_sword:
- name: "&6Pfirsichholz Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oTribut von dem klassischen Zombiefilm..."
- - ""
- soul_sword:
- name: "&6Seelen Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oDie Seele des Teufels ist hier injiziert..."
- - "&b&k|&b- &e&oRechtsklick &7&oum ein leises Knurren zu machen..."
- - "&b&k|&b- &7&oÄndere &7&odeine &e&osicherheit &7&oin &e&oheilung&7&o..."
- - ""
- sky_sword:
- name: "&6Himmelbrechendes Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oHimmelbrecher, was für ein herrschsüchtiger Name..."
- - "&b&k|&b- &e&oRechtsklick &7&oum zum Himmel zu eilen..."
- - ""
- devil_sword:
- name: "&6Demon Slayer Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oDemon Slayer, was für ein mächtiger Titel..."
- - "&b&k|&b- &e&oRechts klicken &7&oum das heilige Feuer zu verwenden, damit alle in Dunkelheit gefegt werden..."
- - ""
- sky_devil_sword:
- name: "&6Kaputtes Himmels-Dämon Schwert"
- lore:
- - ""
- - "&b&k|&b- &7&oDurchbrechen des Himmels und Schneiden des Teufels, einer nach dem anderen emittiert starke Energie..."
- - ""
- - ""
-lores:
- per-use: "&7pro Verwendung"
- not-appraised: "&b&k|&b- &7&oNicht abgeschätzt"
- appraised: "&b&k|&b- &7&oAngewandt &b| &dLevel: &e&l{0}"
- click-to-open: "&7\u21E8 &aKlicke zum Öffnen"
-researches:
- food: "Bump Essen"
- random_equipment: "Zufälliges Equipment"
- appraise: "Gutachten"
- stuff: "Magische Sachen"
- old_stuff: "Gold erhalten"
- bow: "Bump Bogen"
- peach_sword: "Pfirsichholz"
- normal_sword: "Normales Schwert"
- soul_sword: "Seelen Schwert"
- sky_devil: "Himmel oder Dämonen"
-messages:
- no-permission: "Sie haben keine Berechtigung."
- no-input: "&cBitte füge Elemente ein."
- output-no-space: "&cKein Ausgabesatz!"
- not-enough-power: "&cNicht genug Energie."
- stacked: "&cDu kannst diesen Gegenstand nicht verwenden, wenn er gestapelt wurde."
- legacy: "&cDu verwendest ein altes Item. Du musst es auf ein neues upgraden."
-appraise_info:
- attribute:
- weight: "&7Gewicht: &b{0}%"
-
diff --git a/src/main/resources/lang/en-GB.yml b/src/main/resources/lang/en-GB.yml
deleted file mode 100644
index 6eefb8ec..00000000
--- a/src/main/resources/lang/en-GB.yml
+++ /dev/null
@@ -1,385 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Armour"
- food: "&bBump - Food"
- machine: "&bBump - Machine"
- stuff: "&bBump - Stuff"
- tool: "&bBump - Tool"
- weapon: "&bBump - Magic Weapon"
- appraise_info: "&eBump - Appraise Information"
- wiki: "&eBump - Wiki"
-items:
- random_helmet:
- name: "&6Random Helmet"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- random_horse_armor:
- name: "&6Random Horse Armour"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&k|&b- Very sweet and sweet, still bubbling!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- The ice is full of strength, and if you drink it, you can fly!"
- - ""
- fangbianmian:
- name: "&eMaster Kong instant noodle"
- lore:
- - ""
- - "&b&k|&b- This taste is spicy!!"
- - ""
- latiao:
- name: "&eSpicy gluten"
- lore:
- - ""
- - "&b&k|&b- Cool! I still don't forget to lick the spicy oil after eating..."
- - ""
- kouxiangtang:
- name: "&eChewing Gum"
- lore:
- - ""
- - "&b&k|&b- Very sticky..."
- - ""
- zongzi:
- name: "&aRice dumpling"
- lore:
- - ""
- - "&b&k|&b- Happy Dragon Boat Festival!"
- - ""
- appraisal:
- name: "&bAppraisal instrument"
- lore:
- - ""
- - "&c&k|&7- Oh! A defective instrument..."
- - ""
- attribute_grindstone:
- name: "&bAttribute Grindstone"
- lore:
- - ""
- - "&c&k|&7- It is able to purge attributes..."
- - ""
- sun_energy:
- name: "&ePhotosynthetic Energy"
- lore:
- - ""
- - "&b&k|&b- Mutated plants will also photosynthesize..."
- - ""
- mecha_gear:
- name: "&eMechanical Gear"
- lore:
- - ""
- - "&b&k|&b- Something eliminated by a large factory..."
- - ""
- old_coin:
- name: "&eBroken Gold Coin"
- lore:
- - ""
- - "&b&k|&b- What can I buy..."
- - ""
- make:
- name: "&eComputer Technology Core"
- lore:
- - ""
- - "&b&k|&b- What is it used for..."
- - ""
- old_cpu:
- name: "&eBroken CPU"
- lore:
- - ""
- - "&b&k|&b- From which computer it was removed..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- Intact..."
- - ""
- soul_paper:
- name: "&eSoul Talisman"
- lore:
- - ""
- - "&b&k|&b- The power of the soul"
- - ""
- ksf_stuff:
- name: "&eInstant Noodle Seasoning"
- lore:
- - ""
- - "&b&k|&b- Sizzle~ It's spicy"
- - ""
- water_sugar:
- name: "&eSoda Candy"
- lore:
- - ""
- - "&b&k|&b- Sprite? Or Coca-Cola?"
- - ""
- peach_wood:
- name: "&ePeach Wood"
- lore:
- - ""
- - "&b&k|&b- Refuge From Evil Spirits"
- - ""
- update_power:
- name: "&eUpgrade Core"
- lore:
- - ""
- - "&b&k|&b- Used to upgrade some weird items..."
- - ""
- compressed_random_equipment:
- name: "&eCompressed Random Equipment"
- lore:
- - ""
- - "&b&k|&b- Can't be used any more... Crap..."
- - ""
- getgold_spade:
- name: "&eGetting-gold Shovel"
- lore:
- - ""
- - "&b&k|&b- There is a certain chance to dig out broken gold coins in the sand!"
- - ""
- quality_identifier:
- name: "&eQuality Identifier"
- lore:
- - ""
- - "&b&k|&b- Add some random attributes for applicable items!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_armor:
- name: "&eArmour Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random armour attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_damage:
- name: "&eWeapon Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random attack attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_horse_armor:
- name: "&eHorse Armour Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random armour attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- light_bow:
- name: "&6God's Punishment Bow"
- lore:
- - ""
- - "&b&k|&b- &7&oAccept God's punishment..."
- - ""
- witherskull_bow:
- name: "&6Withered Bow"
- lore:
- - ""
- - "&b&k|&b- &7&oWhat it launches is every undead..."
- - ""
- emer_sword:
- name: "&6Emerald Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oMade of expensive emeralds..."
- - ""
- bone_sword:
- name: "&6Bone Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oVery hard..."
- - ""
- random_sword:
- name: "&6Random Short Edge"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- guard_sword:
- name: "&6Guardian Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oI will guard you until the last moment of life"
- - ""
- peach_sword:
- name: "&6Peach Wood Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oTribute to the classic zombie movie..."
- - ""
- soul_sword:
- name: "&6Soul Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oThe soul of the devil is injected here..."
- - "&b&k|&b- &e&oRight click &7&oto make a low growl..."
- - "&b&k|&b- &7&oTurn &7&oyour &e&osatiety &7&ointo &e&ohealth&7&o..."
- - ""
- sky_sword:
- name: "&6Heaven Breaking Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oHeaven Breaking,what a domineering name..."
- - "&b&k|&b- &e&oRight click &7&oand rush to the sky..."
- - ""
- devil_sword:
- name: "&6Demon Slayer Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oDemon Slayer, what a mighty title..."
- - "&b&k|&b- &e&oRight click &7&oto send out the holy fire to sweep all darkness..."
- - ""
- sky_devil_sword:
- name: "&6Heaven-demon Crumble Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oBreaking the sky and cutting the devil, one after another emits powerful energy..."
- - "&b&k|&b- &e&oRight-click &7&oto launch three dragon breaths forward in a row and strengthen yourself..."
- - ""
-lores:
- per-use: "&7per use"
- not-appraised: "&b&k|&b- &7&oNot appraised"
- appraised: "&b&k|&b- &7&oAppraised &b| &dLevel: &e&l{0}"
- click-to-open: "&7\u21E8 &aClick to open"
- any-random-equipment: "&fAny random equipment"
-recipes:
- compressor_mock:
- name: "&bCompressor"
- lore:
- - "&7Craft this Item as shown"
- - "&7using a Compressor"
-researches:
- food: "Bump food"
- random_equipment: "Random equipment"
- appraise: "Appraise"
- stuff: "Magical stuff"
- old_stuff: "Getting gold"
- bow: "Bump bows"
- peach_sword: "Peach sword"
- normal_sword: "Normal sword"
- soul_sword: "Soul sword"
- sky_devil: "Heaven or Demon"
-messages:
- no-permission: "&cYou don't have permission."
- no-input: "&cPlease put in items."
- output-no-space: "&cNo output space!"
- not-enough-power: "&cNot enough energy."
- stacked: "&cYou cannot use this item when stacked."
- legacy: "&cYou are using a legacy item. You will need to upgrade it to new one."
- deprecated: "&cYou are using a deprecated item, it will be removed soon."
- click-here: "&eClick here:"
- food:
- cooldown: "&b&k|&b- &7&oYou need to wait for a while to eat this again!"
- xuebi: "&b&k|&b- &7&oA cool summer!!"
- kele: "&b&k|&b- &7&oThe victory of the fat otaku!"
- fangbianmian: "&b&k|&b- &7&oThe taste of childhood!"
- latiao: "&b&k|&b- &7&oThis is spicy enough!"
- kouxiangtang: "&b&k|&b- &7&oFairy spirit fluttering!"
- zongzi: "&b&k|&b- &7&oSweet or savory?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG, gold..."
- appraisal_paper:
- legacy: "&bYour legacy quality identifiers have been upgraded."
- invalid: "&cThis item is not appraisable!"
- success: "&aThis item can be appraised now!"
- weapon:
- unavailable: "&b&k|&b- &7&oYou cannot activate this skill now!"
- low-food-level: "&b&k|&b- &7&oYour food level is not enough to convert your health!"
- cooldown: "&b&k|&b- &7&oYou need to wait for a while to use weapon abilities!"
- soul_sword:
- converted-part: "&b&k|&b- &7&oPart of your food level has been converted into health!"
- converted-all: "&b&k|&b- &7&oAll of your food level has been converted into health!"
- devil_sword: "&b&k|&b- &7&oDemon Slayer, bring justice from the sky!"
- sky_sword:
- activated: "&b&k|&b- &7&oHeaven Breaking, soar into the sky!"
- protected: "&b&k|&b- &7&oHeaven Breaking Sword protected you from fall damage!"
- sky_devil_sword:
- activated: "&b&k|&b- &7&oDemon Slayer or Heaven Breaking, only to the justice!"
- deactivated: "&b&k|&b- &7&oThe strengthening time is over!"
- light_bow: "&b&k|&b- &7&oGod punishes!"
- wither_skull_bow: "&b&k|&b- &7&oWithering!"
- machine:
- appraisal:
- invalid: "&cThe item does not support being appraised!"
- not-accepted: "&cCurrent appraise type does not accept this item."
- appraised: "&cSorry that the item cannot be identified or has already been appraised!"
- success: "&aAppraisal!"
- attribute-grindstone:
- invalid: "&cThis item is not appraised yet."
- success: "&aThe appraisal result is purged!"
-console:
- loading-appraise-types: "Loading appraise types from config."
- loading-appraise-type: "Loading appraise type \"{0}\"."
- disabled-appraise-type: "The appraise type \"{0}\" is disabled, ignoring."
- loaded-appraise-type: "Loaded appraise type \"{0}\"."
- error-loading-appraise-type: "An error has occurred while loading appraise type \"{0}\": {1}"
- missing-appraise-stars: "Config section 'appraise.stars' is missing."
- use-default-appraise-stars: "Using default appraise stars settings."
- invalid-appraise-stars: "You can only set appraise stars to between 0 and 127!"
- error-sound: "An error has occurred while loading sound config: {0}"
- invalid-sound-config: "Cannot find sound config for BumpSound: {0}"
- invalid-sound-volume: "Invalid sound volume for BumpSound \"{0}\": {1} (must be at least {2})"
- invalid-sound-pitch: "Invalid sound pitch for BumpSound \"{0}\": {1} (must be at least {2})"
-gui:
- appraise:
- name: "&eClick to appraise"
- lore:
- - "&7<- Put the items to be appraised on the left side"
- - "&7Click here to appraise"
- appraise_type_selector:
- name: "&bCurrent type: &e{0}"
- lore:
- - ""
- - "&7View details in Bump's category"
- - "&eClick to select type"
- appraise_type_selector_menu:
- title: "&6Select appraise type"
- lore:
- - ""
- - "&eClick to select this type"
- appraisal_paper:
- name: "&eClick to apply"
- lore:
- - "&7<- Put items on the left side"
- - "&7Click here to allow the item to be appraised"
- grind:
- name: "&eClick to purge attributes"
- lore:
- - "&7<- Put appraised items on the left side"
- - "&7Click here to purge attributes"
-appraise_info:
- name: "&bAppraise type: &e{0}"
- click: "&eClick to view details"
- equipment_type:
- name: "&aApplicable equipment type: &b{0}"
- any: "&7Any item"
- vanilla: "&7Vanilla items only"
- slimefun: "&7Slimefun items only"
- material:
- name: "&aCheck equipment material: &b{0}"
- lore_enabled:
- - "&7Only these materials are accepted:"
- lore_enabled_more: "&7And {0} more..."
- lore_disabled:
- - "&7Material will not be checked."
- equipment_slot:
- name: "&aEquipment slots"
- lore:
- - "&7Attributes will be applied"
- - "&7to the equipment slot(s):"
- attribute:
- name: "&eAttribute: &9{0}"
- range: "&7Range: &b{0} &7~ &b{1}"
- weight: "&7Weight: &b{0}%"
-
diff --git a/src/main/resources/lang/en-US.yml b/src/main/resources/lang/en-US.yml
deleted file mode 100644
index 498a1554..00000000
--- a/src/main/resources/lang/en-US.yml
+++ /dev/null
@@ -1,386 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Armor"
- food: "&bBump - Food"
- machine: "&bBump - Machine"
- stuff: "&bBump - Stuff"
- tool: "&bBump - Tool"
- weapon: "&bBump - Magic Weapon"
- appraise_info: "&eBump - Appraise Information"
- wiki: "&eBump - Wiki"
-items:
- random_helmet:
- name: "&6Random Helmet"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- random_horse_armor:
- name: "&6Random Horse Armor"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&k|&b- Very sweet and sweet, still bubbling!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- The ice is full of strength, and if you drink it, you can fly!"
- - ""
- fangbianmian:
- name: "&eMaster Kong instant noodle"
- lore:
- - ""
- - "&b&k|&b- This taste is spicy!!"
- - ""
- latiao:
- name: "&eSpicy gluten"
- lore:
- - ""
- - "&b&k|&b- Cool! I still don't forget to lick the spicy oil after eating..."
- - ""
- kouxiangtang:
- name: "&eChewing Gum"
- lore:
- - ""
- - "&b&k|&b- Very sticky..."
- - ""
- zongzi:
- name: "&aZongzi"
- lore:
- - ""
- - "&b&k|&b- Happy Dragon Boat Festival!"
- - ""
- appraisal:
- name: "&bAppraisal instrument"
- lore:
- - ""
- - "&c&k|&7- Oh! A defective instrument..."
- - ""
- attribute_grindstone:
- name: "&bAttribute Grindstone"
- lore:
- - ""
- - "&c&k|&7- It is able to purge attributes..."
- - ""
- sun_energy:
- name: "&ePhotosynthetic Energy"
- lore:
- - ""
- - "&b&k|&b- Mutated plants will also photosynthesize..."
- - ""
- mecha_gear:
- name: "&eMechanical Gear"
- lore:
- - ""
- - "&b&k|&b- Something eliminated by a large factory..."
- - ""
- old_coin:
- name: "&eBroken Gold Coin"
- lore:
- - ""
- - "&b&k|&b- What can I buy..."
- - ""
- make:
- name: "&eComputer Technology Core"
- lore:
- - ""
- - "&b&k|&b- What is it used for..."
- - ""
- old_cpu:
- name: "&eBroken CPU"
- lore:
- - ""
- - "&b&k|&b- From which computer it was removed..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- Intact..."
- - ""
- soul_paper:
- name: "&eSoul Talisman"
- lore:
- - ""
- - "&b&k|&b- The power of the soul"
- - ""
- ksf_stuff:
- name: "&eInstant Noodle Seasoning"
- lore:
- - ""
- - "&b&k|&b- Sizzle~ It's spicy"
- - ""
- water_sugar:
- name: "&eSoda Candy"
- lore:
- - ""
- - "&b&k|&b- Sprite? Or Coca-Cola?"
- - ""
- peach_wood:
- name: "&ePeach Wood"
- lore:
- - ""
- - "&b&k|&b- Refuge From Evil Spirits"
- - ""
- update_power:
- name: "&eUpgrade Core"
- lore:
- - ""
- - "&b&k|&b- Used to upgrade some weird items..."
- - ""
- compressed_random_equipment:
- name: "&eCompressed Random Equipment"
- lore:
- - ""
- - "&b&k|&b- Can't be used any more... Crap..."
- - ""
- getgold_spade:
- name: "&eGetting-gold Shovel"
- lore:
- - ""
- - "&b&k|&b- There is a certain chance to dig out broken gold coins in the sand!"
- - ""
- quality_identifier:
- name: "&eQuality Identifier"
- lore:
- - ""
- - "&b&k|&b- Add some random attributes for applicable items!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_armor:
- name: "&eArmor Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random armor attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_damage:
- name: "&eWeapon Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random attack attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- appraisal_paper_horse_armor:
- name: "&eHorse Armor Quality Identifier"
- lore:
- - ""
- - "&b&k|&b- A random armor attribute for a given item!"
- - "&b&k|&b- Very expensive, be sure to keep it..."
- - ""
- light_bow:
- name: "&6God's Punishment Bow"
- lore:
- - ""
- - "&b&k|&b- &7&oAccept God's punishment..."
- - ""
- witherskull_bow:
- name: "&6Withered Bow"
- lore:
- - ""
- - "&b&k|&b- &7&oWhat it launches is every undead..."
- - ""
- emer_sword:
- name: "&6Emerald Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oMade of expensive emeralds..."
- - ""
- bone_sword:
- name: "&6Bone Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oVery hard..."
- - ""
- random_sword:
- name: "&6Random Short Edge"
- lore:
- - ""
- - "&b&k|&b- &7&oHow is my luck..."
- - "&b&k|&b- &e&oThe appraiser &7&orandomly gives this attribute..."
- guard_sword:
- name: "&6Guardian Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oI will guard you until the last moment of life"
- - ""
- peach_sword:
- name: "&6Peach Wood Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oTribute to the classic zombie movie..."
- - ""
- soul_sword:
- name: "&6Soul Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oThe soul of the devil is injected here..."
- - "&b&k|&b- &e&oRight click &7&oto make a low growl..."
- - "&b&k|&b- &7&oTurn &7&oyour &e&osatiety &7&ointo &e&ohealth&7&o..."
- - ""
- sky_sword:
- name: "&6Heaven Breaking Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oHeaven Breaking,what a domineering name..."
- - "&b&k|&b- &e&oRight click &7&oand rush to the sky..."
- - ""
- devil_sword:
- name: "&6Demon Slayer Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oDemon Slayer, what a mighty title..."
- - "&b&k|&b- &e&oRight click &7&oto send out the holy fire to sweep all darkness..."
- - ""
- sky_devil_sword:
- name: "&6Heaven-demon Crumble Sword"
- lore:
- - ""
- - "&b&k|&b- &7&oBreaking the sky and cutting the devil, one after another emits powerful energy..."
- - "&b&k|&b- &e&oRight-click &7&oto launch three dragon breaths forward in a row and strengthen yourself..."
- - ""
-lores:
- per-use: "&7per use"
- not-appraised: "&b&k|&b- &7&oNot appraised"
- appraised: "&b&k|&b- &7&oAppraised &b| &dLevel: &e&l{0}"
- click-to-open: "&7\u21E8 &aClick to open"
- any-random-equipment: "&fAny random equipment"
-recipes:
- compressor_mock:
- name: "&bCompressor"
- lore:
- - "&7Craft this Item as shown"
- - "&7using a Compressor"
-researches:
- food: "Bump food"
- random_equipment: "Random equipment"
- appraise: "Appraise"
- stuff: "Magical stuff"
- old_stuff: "Getting gold"
- bow: "Bump bows"
- peach_sword: "Peach sword"
- normal_sword: "Normal sword"
- soul_sword: "Soul sword"
- sky_devil: "Heaven or Demon"
-messages:
- no-permission: "&cYou don't have permission."
- no-input: "&cPlease put in items."
- output-no-space: "&cNo output space!"
- not-enough-power: "&cNot enough energy."
- stacked: "&cYou cannot use this item when stacked."
- legacy: "&cYou are using a legacy item. You will need to upgrade it to new one."
- deprecated: "&cYou are using a deprecated item, it will be removed soon."
- click-here: "&eClick here:"
- food:
- cooldown: "&b&k|&b- &7&oYou need to wait for a while to eat this again!"
- xuebi: "&b&k|&b- &7&oA cool summer!!"
- kele: "&b&k|&b- &7&oThe victory of the fat otaku!"
- fangbianmian: "&b&k|&b- &7&oThe taste of childhood!"
- latiao: "&b&k|&b- &7&oThis is spicy enough!"
- kouxiangtang: "&b&k|&b- &7&oFairy spirit fluttering!"
- zongzi: "&b&k|&b- &7&oSweet or savory?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG, gold..."
- appraisal_paper:
- legacy: "&bYour legacy quality identifiers have been upgraded."
- invalid: "&cThis item is not appraisable!"
- success: "&aThis item can be appraised now!"
- weapon:
- unavailable: "&b&k|&b- &7&oYou cannot activate this skill now!"
- low-food-level: "&b&k|&b- &7&oYour food level is not enough to convert your health!"
- cooldown: "&b&k|&b- &7&oYou need to wait for a while to use weapon abilities!"
- soul_sword:
- converted-part: "&b&k|&b- &7&oPart of your food level has been converted into health!"
- converted-all: "&b&k|&b- &7&oAll of your food level has been converted into health!"
- devil_sword: "&b&k|&b- &7&oDemon Slayer, bring justice from the sky!"
- sky_sword:
- activated: "&b&k|&b- &7&oHeaven Breaking, soar into the sky!"
- protected: "&b&k|&b- &7&oHeaven Breaking Sword protected you from fall damage!"
- sky_devil_sword:
- activated: "&b&k|&b- &7&oDemon Slayer or Heaven Breaking, only to the justice!"
- deactivated: "&b&k|&b- &7&oThe strengthening time is over!"
- light_bow: "&b&k|&b- &7&oGod punishes!"
- wither_skull_bow: "&b&k|&b- &7&oWithering!"
- machine:
- appraisal:
- invalid: "&cThe item does not support being appraised!"
- not-accepted: "&cCurrent appraise type does not accept this item."
- appraised: "&cSorry that the item cannot be identified or has already been appraised!"
- success: "&aAppraisal!"
- attribute-grindstone:
- invalid: "&cThis item is not appraised yet."
- success: "&aThe appraisal result is purged!"
-console:
- loading-appraise-types: "Loading appraise types from config."
- loading-appraise-type: "Loading appraise type \"{0}\"."
- disabled-appraise-type: "The appraise type \"{0}\" is disabled, ignoring."
- loaded-appraise-type: "Loaded appraise type \"{0}\"."
- error-loading-appraise-type: "An error has occurred while loading appraise type \"{0}\": {1}"
- missing-appraise-stars: "Config section 'appraise.stars' is missing."
- use-default-appraise-stars: "Using default appraise stars settings."
- invalid-appraise-stars: "You can only set appraise stars to between 0 and 127!"
- error-sound: "An error has occurred while loading sound config: {0}"
- invalid-sound-config: "Cannot find sound config for BumpSound: {0}"
- invalid-sound-volume: "Invalid sound volume for BumpSound \"{0}\": {1} (must be at least {2})"
- invalid-sound-pitch: "Invalid sound pitch for BumpSound \"{0}\": {1} (must be at least {2})"
-gui:
- appraise:
- name: "&eClick to appraise"
- lore:
- - "&7<- Put the items to be appraised on the left side"
- - "&7Click here to appraise"
- appraise_type_selector:
- name: "&bCurrent type: &e{0}"
- lore:
- - ""
- - "&7View details in Bump's category"
- - "&eClick to select type"
- appraise_type_selector_menu:
- title: "&6Select appraise type"
- lore:
- - ""
- - "&eClick to select this type"
- appraisal_paper:
- name: "&eClick to apply"
- lore:
- - "&7<- Put items on the left side"
- - "&7Click here to allow the item to be appraised"
- grind:
- name: "&eClick to purge attributes"
- lore:
- - "&7<- Put appraised items on the left side"
- - "&7Click here to purge attributes"
-appraise_info:
- name: "&bAppraise type: &e{0}"
- click: "&eClick to view details"
- equipment_type:
- name: "&aApplicable equipment type: &b{0}"
- any: "&7Any item"
- vanilla: "&7Vanilla items only"
- slimefun: "&7Slimefun items only"
- material:
- name: "&aCheck equipment material: &b{0}"
- lore_enabled:
- - "&7Only these materials are accepted:"
- lore_enabled_more: "&7And {0} more..."
- lore_disabled:
- - "&7Material will not be checked."
- equipment_slot:
- name: "&aEquipment slots"
- lore:
- - "&7Attributes will be applied"
- - "&7to the equipment slot(s):"
- attribute:
- name: "&eAttribute: &9{0}"
- range: "&7Range: &b{0} &7~ &b{1}"
- weight: "&7Weight: &b{0}%"
-attributes:
-
diff --git a/src/main/resources/lang/en.yml b/src/main/resources/lang/en.yml
new file mode 100644
index 00000000..e8e94437
--- /dev/null
+++ b/src/main/resources/lang/en.yml
@@ -0,0 +1,468 @@
+items:
+ # item groups
+ _IG_MAIN:
+ conditions:
+ force-load: true
+ name: "&bBump"
+ _IG_WIKI:
+ conditions:
+ force-load: true
+ name: "&eBump - Wiki"
+ lore:
+ - ""
+ - "&7\u21E8 &aClick to open"
+ _IG_MATERIALS:
+ conditions:
+ force-load: true
+ name: "&bBump - Materials"
+ _IG_FOOD:
+ conditions:
+ force-load: true
+ name: "&bBump - Food"
+ _IG_TOOLS:
+ conditions:
+ force-load: true
+ name: "&bBump - Tools"
+ _IG_MACHINES:
+ conditions:
+ force-load: true
+ name: "&bBump - Machines"
+ _IG_ARMOR:
+ conditions:
+ force-load: true
+ name: "&bBump - Armor"
+ _IG_WEAPONS:
+ conditions:
+ force-load: true
+ name: "&bBump - Weapons"
+ _IG_APPRAISE_INFO:
+ conditions:
+ force-load: true
+ name: "&eBump - Appraise Information"
+
+ # recipe types
+ _RECIPE_GET_GOLD_SPADE:
+ conditions:
+ force-load: true
+ name: "&eGetting-gold Spade"
+
+ # ui items
+ _UI_QUALITY_IDENTIFIER_USE:
+ conditions:
+ force-load: true
+ name: "&eClick to use Quality Identifier"
+ lore:
+ - ""
+ - "&7<- Put the item to be identified on the left side"
+ - ""
+ - "&7Click here to check if the item can be appraised"
+ - "&7(i.e. the item can be accepted by any appraise type)"
+ - ""
+ - "&7If the item can be appraised, it will be marked as appraisable."
+ _UI_APPRAISER_USE:
+ conditions:
+ force-load: true
+ name: "&eClick to appraise"
+ lore:
+ - ""
+ - "&7<- Put the item to be appraised on the left side"
+ - ""
+ - "&7Click here to appraise"
+ _UI_APPRAISER_SELECTOR:
+ conditions:
+ force-load: true
+ partial-override: true
+ name: "&bClick to select a new appraise type"
+ lore:
+ - ""
+ - "&7Current appraise type:"
+ _UI_APPRAISER_SELECTOR_INFO:
+ conditions:
+ force-load: true
+ name: "&eSelect an appraise type"
+ lore:
+ - "&7This page lists all available appraise types for you."
+ - "&7Click on an appraise type to select it."
+ - ""
+ - "&7You can check the details of the appraise type"
+ - "&7in the appraise types menu."
+ _UI_ATTRIBUTE_GRINDSTONE_USE:
+ conditions:
+ force-load: true
+ name: "&eClick to purge attributes"
+ lore:
+ - ""
+ - "&7<- Put appraised items on the left side"
+ - ""
+ - "&7Click here to purge attributes"
+ _UI_APPRAISE_MENU_INFO:
+ conditions:
+ force-load: true
+ name: "&eAppraise types"
+ lore:
+ - "&7This page lists all available appraise types for you."
+ - "&7Click on an appraise type to view its details."
+ _UI_ITEM_CONVERTER_INFO:
+ conditions:
+ force-load: true
+ name: "&eItem Converter"
+ lore:
+ - "&7This machine converts Bump 2 items to Bump 3 items."
+ - ""
+ - "&7Only the item id will be converted,"
+ - "&7everything else are kept."
+ - ""
+ - "&7Items are automatically converted when in input slots,"
+ - "&7no energy is needed."
+
+ # materials
+ PHOTOSYNTHETIC_ENERGY:
+ name: "&ePhotosynthetic Energy"
+ lore:
+ - ""
+ - "&b&k|&b- Mutated plants can also photosynthesize..."
+ - ""
+ MECHANICAL_GEAR:
+ name: "&eMechanical Gear"
+ lore:
+ - ""
+ - "&b&k|&b- Something eliminated from a large factory..."
+ - ""
+ BROKEN_GOLD_COIN:
+ name: "&eBroken Gold Coin"
+ lore:
+ - ""
+ - "&b&k|&b- What can I buy..."
+ - ""
+ COMPUTER_TECH_CORE:
+ name: "&eComputer Technology Core"
+ lore:
+ - ""
+ - "&b&k|&b- What is it used for..."
+ - ""
+ BROKEN_CPU:
+ name: "&eBroken CPU"
+ lore:
+ - ""
+ - "&b&k|&b- Where was it removed from..."
+ - ""
+ CPU:
+ name: "&eCPU"
+ lore:
+ - ""
+ - "&b&k|&b- It is intact..."
+ - ""
+ ANCIENT_RUNE_SOUL:
+ name: "&7Ancient Rune &8&l[&e&lSoul&8&l]"
+ lore:
+ - ""
+ - "&b&k|&b- Infused with the power of the soul..."
+ - ""
+ INSTANT_NOODLE_SEASONING:
+ name: "&eInstant Noodle Seasoning"
+ lore:
+ - ""
+ - "&b&k|&b- Sizzle~ It's spicy"
+ - ""
+ POP_CANDY:
+ name: "&ePop Candy"
+ lore:
+ - ""
+ - "&b&k|&b- What's the flavor?"
+ - "&b&k|&b- Sprite or Coke?"
+ - ""
+ PEACH_WOOD:
+ name: "&ePeach Wood"
+ lore:
+ - ""
+ - "&b&k|&b- Drive away from evil..."
+ - ""
+ UPDATE_CORE:
+ name: "&eUpgrade Core"
+ lore:
+ - ""
+ - "&b&k|&b- Used to upgrade some weird items..."
+ - ""
+ COMPRESSED_RANDOM_EQUIPMENT:
+ name: "&eCompressed Random Equipment"
+ lore:
+ - ""
+ - "&b&k|&b- Can't be used any more... Crap..."
+ - ""
+
+ # food
+ SPRITE:
+ name: "&6Sprite"
+ lore:
+ - ""
+ - "&b&k|&b- Very sweet and still bubbling!"
+ - ""
+ COLA:
+ name: "&eCola"
+ lore:
+ - ""
+ - "&b&k|&b- Iced cola, very refreshing!"
+ - "&b&k|&b- If you drink it, you can fly!"
+ - ""
+ INSTANT_NOODLE:
+ name: "&eMaster Kong Instant Noodle"
+ lore:
+ - ""
+ - "&b&k|&b- The taste is spicy!!"
+ - ""
+ SPICY_STRIPS:
+ name: "&eSpicy Strips"
+ lore:
+ - ""
+ - "&b&k|&b- Cool! I will not forget to lick the spicy oil..."
+ - ""
+ CHEWING_GUM:
+ name: "&eChewing Gum"
+ lore:
+ - ""
+ - "&b&k|&b- Very sticky..."
+ - ""
+ RICE_DUMPLING:
+ name: "&aRice Dumpling"
+ lore:
+ - ""
+ - "&b&k|&b- Happy Dragon Boat Festival!"
+ - ""
+
+ # tools
+ GET_GOLD_SPADE:
+ name: "&eGetting-gold Spade"
+ lore:
+ - ""
+ - "&b&k|&b- Can dig out broken gold coins from sand!"
+ - ""
+ QUALITY_IDENTIFIER:
+ conditions:
+ partial-override: true
+ name: "&eQuality Identifier"
+ lore:
+ - ""
+ - "&b&k|&b- Allow applicable items to be appraise-able!"
+ - "&b&k|&b- Very expensive, be sure to keep it..."
+ - ""
+
+ # machines
+ APPRAISER:
+ name: "&bAppraiser"
+ lore:
+ - ""
+ - "&c&k|&7- Oh! A defective instrument..."
+ - ""
+ ATTRIBUTE_GRINDSTONE:
+ name: "&bAttribute Grindstone"
+ lore:
+ - ""
+ - "&c&k|&7- It is able to purge attributes..."
+ - ""
+ ITEM_CONVERTER:
+ name: "&bItem Converter"
+ lore:
+ - ""
+ - "&c&k|&7- Convert Bump 2 items to Bump 3 items..."
+ - ""
+
+ # armor
+ RANDOM_HELMET:
+ conditions:
+ partial-override: true
+ name: "&6Random Helmet"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+ RANDOM_CHESTPLATE:
+ conditions:
+ partial-override: true
+ name: "&6Random Chestplate"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+ RANDOM_LEGGINGS:
+ conditions:
+ partial-override: true
+ name: "&6Random Leggings"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+ RANDOM_BOOTS:
+ conditions:
+ partial-override: true
+ name: "&6Random Boots"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+ RANDOM_HORSE_ARMOR:
+ conditions:
+ partial-override: true
+ name: "&6Random Horse Armor"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+
+ # weapons
+ RANDOM_SWORD:
+ name: "&6Random Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHow is my luck..."
+ - "&b&k|&b- &e&oThe appraiser &7&orandomly adds more attributes..."
+ LIGHTNING_BOW:
+ name: "&6God's Punishment Bow"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oAccept punishment from the god..."
+ - ""
+ WITHER_SKULL_BOW:
+ name: "&6Withered Bow"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oWhat it launches is every undead..."
+ - ""
+ EMERALD_SWORD:
+ name: "&6Emerald Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oMade of expensive emeralds..."
+ - ""
+ BONE_SWORD:
+ name: "&6Bone Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oVery hard..."
+ - ""
+ GUARDIAN_SWORD:
+ name: "&6Guardian Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oI will guard you until the last moment of your life"
+ - ""
+ PEACH_WOOD_SWORD:
+ name: "&6Peach Wood Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oTribute to the classic zombie movie..."
+ - ""
+ SOUL_SWORD:
+ name: "&6Soul Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oThe soul of the devil is injected here..."
+ - "&b&k|&b- &e&oRight click &7&oto make a low growl..."
+ - "&b&k|&b- &7&oTurn &7&oyour &e&ohunger &7&ointo &e&ohealth&7&o..."
+ - ""
+ HEAVEN_BREAKING_SWORD:
+ name: "&6Heaven Breaking Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oHeaven Breaking, what a domineering name..."
+ - "&b&k|&b- &e&oRight click &7&oto rush into the sky..."
+ - "&b&k|&b- &7&oOnce you fall, you will be protected by the sword..."
+ - ""
+ DEMON_SLAYER_SWORD:
+ name: "&6Demon Slayer Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oDemon Slayer, what a mighty name..."
+ - "&b&k|&b- &e&oRight click &7&oto send out the holy fire"
+ - "&b&k|&b- &7&oto sweep all darkness..."
+ - ""
+ HEAVEN_BREAKING_DEMON_SLAYER_SWORD:
+ name: "&6Heaven Breaking & Demon Slayer Sword"
+ lore:
+ - ""
+ - "&b&k|&b- &7&oBreaking the sky and slay the demon,"
+ - "&b&k|&b- &7&oone after another emits powerful energy..."
+ - "&b&k|&b- &e&oRight-click &7&oto launch three dragon breaths"
+ - "&b&k|&b- &7&oforward in a row and strengthen yourself..."
+ - ""
+lores:
+ per-use: "&7per use"
+ not-appraised: "&b&k|&b- &7&oNot appraised"
+ appraised: "&b&k|&b- &7&oAppraised &b| &dLevel: &e&l{0}"
+ any-random-equipment: "&fAny \"Random Equipment\""
+ appraise_info:
+ equipment_type:
+ name: "&aAcceptable equipment type: &b{0}"
+ any: "&7Any item"
+ vanilla: "&7Non-Slimefun items only"
+ slimefun: "&7Slimefun items only"
+ material:
+ name: "&aCheck material"
+ enabled: "&7Only these materials are accepted:"
+ enabled_more: "&7And {0} more..."
+ disabled: "&7Material will not be checked."
+ equipment_slot:
+ name: "&aEquipment slots"
+ lore: "&7Attributes will be applied to the equipment slot(s):"
+ attribute:
+ name: "&eAttribute: &9{0}"
+ range: "&7Range: &b{0} &7~ &b{1}"
+ weight: "&7Weight: &b{0}%"
+researches:
+ materials: "Bump materials"
+ food: "Bump food"
+ get_gold: "Getting gold"
+ appraise: "Appraise"
+ random_equipment: "Random equipment"
+ bow: "Bump bows"
+ peach_sword: "Peach sword"
+ normal_sword: "Normal sword"
+ soul_sword: "Soul sword"
+ heaven_hell: "Heaven or Hell"
+messages:
+ no-permission: "&cYou don't have permission."
+ no-input: "&cPlease put in items."
+ output-no-space: "&cNo output space!"
+ not-enough-power: "&cNot enough energy."
+ stacked: "&cYou cannot use this item when stacked."
+ legacy: "&cYou are using a legacy item. You will need to upgrade it to new one."
+ deprecated: "&cYou are using a deprecated item, it will be removed soon."
+ click-here: "&eClick here:"
+ food:
+ cooldown: "&b&k|&b- &7&oYou need to wait for a while to eat this again!"
+ sprite: "&b&k|&b- &7&oA cool summer!!"
+ cola: "&b&k|&b- &7&oThe victory of the fat otaku!"
+ instant_noodle: "&b&k|&b- &7&oThe taste of childhood!"
+ spicy_strips: "&b&k|&b- &7&oThis is spicy enough!"
+ chewing_gum: "&b&k|&b- &7&oFairy spirit fluttering!"
+ rice_dumpling: "&b&k|&b- &7&oSweet or savory?"
+ tool:
+ get_gold_spade: "&b&k|&b- &7&oOMG, gold..."
+ quality_identifier:
+ invalid: "&cThis item cannot be marked appraisable!"
+ success: "&aThis item is marked appraisable now!"
+ weapon:
+ unavailable: "&b&k|&b- &7&oYou cannot activate the ability now!"
+ low-food-level: "&b&k|&b- &7&oYour food level is not enough to activate the ability!"
+ cooldown: "&b&k|&b- &7&oYou need to wait for a while to use weapon abilities!"
+ lightning_bow: "&b&k|&b- &7&oGod punishes!"
+ wither_skull_bow: "&b&k|&b- &7&oWithering!"
+ soul_sword:
+ converted-part: "&b&k|&b- &7&oPart of your food level has been converted into health!"
+ converted-all: "&b&k|&b- &7&oAll of your food level has been converted into health!"
+ heaven_breaking_sword:
+ activated: "&b&k|&b- &7&oHeaven Breaking, soar into the sky!"
+ protected: "&b&k|&b- &7&oHeaven Breaking Sword protected you from fall damage!"
+ demon_slayer_sword: "&b&k|&b- &7&oDemon Slayer, bring justice from the sky!"
+ heaven_breaking_demon_slayer_sword:
+ activated: "&b&k|&b- &7&oDemon Slayer or Heaven Breaking, only to the justice!"
+ deactivated: "&b&k|&b- &7&oThe strengthening time is over!"
+ machine:
+ appraiser:
+ selector_title: "&bSelect an appraise type"
+ invalid: "&cThis item cannot be appraised!"
+ not-accepted: "&cCurrent appraise type does not accept this item."
+ appraised: "&cThis item cannot be appraised or is already appraised!"
+ success: "&aAppraisal!"
+ attribute-grindstone:
+ invalid: "&cThis item is not appraised yet."
+ success: "&aThe appraisal result is purged!"
diff --git a/src/main/resources/lang/es-ES.yml b/src/main/resources/lang/es-ES.yml
deleted file mode 100644
index 5b56df98..00000000
--- a/src/main/resources/lang/es-ES.yml
+++ /dev/null
@@ -1,81 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Armadura"
- food: "&bBump - Comida"
- machine: "&bBump - Máquina"
- stuff: "&bBump - Cosas"
- tool: "&bBump - Herramienta"
- weapon: "&bBump - Arma Mágica"
-items:
- random_helmet:
- name: "&6Casco al Azar"
- lore:
- - ""
- - "&b&k|&b- &7&oCómo es mi suerte..."
- - "&b&k|&b- &e&oEl tasador &7&oadjudica este atributo de forma aleatoria..."
- random_horse_armor:
- name: "&6Armadura de Caballo al Azar"
- lore:
- - ""
- - "&b&k|&b- &7&oCómo es mi suerte..."
- - "&b&k|&b- &e&oEl tasador &7&oadjudica este atributo de forma aleatoria..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&k|&b- Muy dulce y goloso, ¡todavía está burbujeando!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- El hielo está lleno de fuerza, y si lo bebes, ¡puedes volar!"
- - ""
- fangbianmian:
- name: "&eFideos instantáneos Master Kong"
- lore:
- - ""
- - "&b&k|&b- ¡¡Este sabor es picante!!"
- - ""
- latiao:
- name: "&eGluten picante"
- lore:
- - ""
- - "&b&k|&b- ¡Genial! Todavía no me olvido de lamer el aceite picante después de comer..."
- - ""
- kouxiangtang:
- name: "&eChicle"
- lore:
- - ""
- - "&b&k|&b- Muy pegajoso..."
- - ""
- zongzi:
- name: "&aBola de masa de arroz"
- lore:
- - ""
- - "&b&k|&b- Feliz Festival del Bote del Dragón!"
- - ""
- appraisal:
- name: "&bInstrumento de evaluación"
- lore:
- - ""
- - "&c&k|&7- ¡Vaya! Un instrumento defectuoso..."
- - ""
- sun_energy:
- name: "&eEnergía fotosintética"
- mecha_gear:
- name: "&eEquipo Mecánico"
- old_coin:
- name: "&eMoneda de Oro Rota"
- make:
- name: "&eNúcleo de tecnología informática"
- old_cpu:
- name: "&eComputadora rota"
- cpu:
- name: "&eCPU"
- ksf_stuff:
- name: "&eCondimento para fideos instantáneos"
-researches:
- food: "Alimento de Bump"
-
diff --git a/src/main/resources/lang/fa-IR.yml b/src/main/resources/lang/fa-IR.yml
deleted file mode 100644
index cd21505a..00000000
--- a/src/main/resources/lang/fa-IR.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-
diff --git a/src/main/resources/lang/fr-FR.yml b/src/main/resources/lang/fr-FR.yml
deleted file mode 100644
index b265181d..00000000
--- a/src/main/resources/lang/fr-FR.yml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - l' armure"
- food: "&bBump - Aliments"
- machine: "&bBump - Machine"
- stuff: "&bBump - Staff"
- tool: "&bBump - l' outil"
- weapon: "&bBump - Arme magique"
-items:
- random_helmet:
- name: "&6Casque aléatoire"
- lore:
- - ""
- - "&b&k|&b- &7&oQuelle est ma chance..."
- - "&b&k|&b- &e&oL'évaluateur &7&odonne cet aléatoire attribut..."
- random_horse_armor:
- name: "&6Armure de cheval aléatoire"
- lore:
- - ""
- - "&b&k|&b- &7&oQuelle est ma chance..."
- - "&b&k|&b- &e&oL'évaluateur &7&odonne cet attribut aléatoirement..."
- xuebi:
- name: "&6Lutin"
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- La glace est pleine de force, et si vous la buvez, vous pouvez voler !"
- - ""
- fangbianmian:
- name: "Nouille instantanée de Maitre Kong"
- lore:
- - ""
- - "&b&k|&b- C'est épicé !!"
- - ""
- appraisal_paper_armor:
- name: "&eIdentificateur de qualité d'armure"
-
diff --git a/src/main/resources/lang/ja-JP.yml b/src/main/resources/lang/ja-JP.yml
deleted file mode 100644
index 70856ce4..00000000
--- a/src/main/resources/lang/ja-JP.yml
+++ /dev/null
@@ -1,385 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - よろい"
- food: "&bBump - 食品"
- machine: "&bBump - 機械"
- stuff: "&bBump - 魔法"
- tool: "&bBump - ツール"
- weapon: "&bBump - 魔法の武器"
- appraise_info: "&eBump - 鑑定情報"
- wiki: "&eBump - ウィキ"
-items:
- random_helmet:
- name: "&6ランダムなヘルメット"
- lore:
- - ""
- - "&b&k|&b- &7&o私の運はどうですかね..."
- - "&b&k|&b- &e&o鑑定機は &7&oこの属性をランダムに与えます..."
- random_horse_armor:
- name: "&6ランダムホースアーマー"
- lore:
- - ""
- - "&b&k|&b- &7&o私の運はどうですかね..."
- - "&b&k|&b- &e&o鑑定機は &7&oこの属性をランダムに与えます..."
- xuebi:
- name: "&6スプライト"
- lore:
- - ""
- - "&b&k|&b- とても甘い、まだ泡立っている!"
- - ""
- kele:
- name: "&eコーラ"
- lore:
- - ""
- - "&b&k|&b- 氷は力満々、飲めば飛べることまでできる"
- - ""
- fangbianmian:
- name: "&e康師傅インスタントラーメン"
- lore:
- - ""
- - "&b&k|&b- この味は辛い!!"
- - ""
- latiao:
- name: "&e辣条"
- lore:
- - ""
- - "&b&k|&b- いいね、食べたら油をなめるのを忘れないでね..."
- - ""
- kouxiangtang:
- name: "&eガム"
- lore:
- - ""
- - "&b&k|&b- とても粘り強い..."
- - ""
- zongzi:
- name: "&aちまき"
- lore:
- - ""
- - "&b&k|&b- 端午の節句おめでとうございます!"
- - ""
- appraisal:
- name: "&b鑑定機械"
- lore:
- - ""
- - "&c&k|&7- うわっ、不良品だ..."
- - ""
- attribute_grindstone:
- name: "&b属性砥石"
- lore:
- - ""
- - "&c&k|&7- 属性を排除できる..."
- - ""
- sun_energy:
- name: "&e光合成エネルギー"
- lore:
- - ""
- - "&b&k|&b- 変異種の植物も光合成されます..."
- - ""
- mecha_gear:
- name: "&e機械ギア"
- lore:
- - ""
- - "&b&k|&b- 大きな工場から捨てたもの"
- - ""
- old_coin:
- name: "&e壊れた金貨"
- lore:
- - ""
- - "&b&k|&b- 何を買えるかな.."
- - ""
- make:
- name: "&eコンピューターテクノロジーコア"
- lore:
- - ""
- - "&b&k|&b- それは何のために使われるかな..."
- - ""
- old_cpu:
- name: "&e壊れたCPU"
- lore:
- - ""
- - "&b&k|&b- 一体誰のコンピューターから抜き出したんだろう..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- 損害無し..."
- - ""
- soul_paper:
- name: "&e魂のタリスマン"
- lore:
- - ""
- - "&b&k|&b- 魂の力"
- - ""
- ksf_stuff:
- name: "&eインスタントラーメンの調味料"
- lore:
- - ""
- - "&b&k|&b- シャー~ 辛いです"
- - ""
- water_sugar:
- name: "&eソーダ飴"
- lore:
- - ""
- - "&b&k|&b- スプライト?それともコーラか?"
- - ""
- peach_wood:
- name: "&e桃の木"
- lore:
- - ""
- - "&b&k|&b- 悪霊からの避難"
- - ""
- update_power:
- name: "&eアップグレイドのコア"
- lore:
- - ""
- - "&b&k|&b- 奇妙なアイテムをアップグレードするために使用される..."
- - ""
- compressed_random_equipment:
- name: "&e圧縮ランダムな装備"
- lore:
- - ""
- - "&b&k|&b- どうやらもう使えません…"
- - ""
- getgold_spade:
- name: "&e金取りのしゃべる"
- lore:
- - ""
- - "&b&k|&b- 砂から壊れた金貨を掘り出すチャンスがあります!"
- - ""
- quality_identifier:
- name: "&e品質鑑定符"
- lore:
- - ""
- - "&b&k|&b- 該当するアイテムにランダムな属性を添加!"
- - "&b&k|&b- とても高価なので、ちゃんと預かるべきです..."
- - ""
- appraisal_paper_armor:
- name: "&e防具品質識別子"
- lore:
- - ""
- - "&b&k|&b- 所与のアイテムのランダムな防具属性!"
- - "&b&k|&b- とても高価なので、ちゃんと預かるべきです..."
- - ""
- appraisal_paper_damage:
- name: "&e武器品質識別子"
- lore:
- - ""
- - "&b&k|&b- 所与のアイテムのランダムな攻撃属性!"
- - "&b&k|&b- とても高価なので、ちゃんと預かるべきです..."
- - ""
- appraisal_paper_horse_armor:
- name: "&e馬の鎧品質識別子"
- lore:
- - ""
- - "&b&k|&b- 所与のアイテムのランダムな防具属性!"
- - "&b&k|&b- とても高価なので、ちゃんと預かるべきです..."
- - ""
- light_bow:
- name: "&6天罰の弓"
- lore:
- - ""
- - "&b&k|&b- &7&o神の懲罰を受け入れたまえ..."
- - ""
- witherskull_bow:
- name: "&6ウィザーの弓"
- lore:
- - ""
- - "&b&k|&b- &7&oそれが射つのは、あらゆるアンデッドなのだ..."
- - ""
- emer_sword:
- name: "&6エメラルドの剣"
- lore:
- - ""
- - "&b&k|&b- &7&o高価なエメラルドで作られた..."
- - ""
- bone_sword:
- name: "&6骨の剣"
- lore:
- - ""
- - "&b&k|&b- &7&o非常に硬い..."
- - ""
- random_sword:
- name: "&6ランダムな短剣"
- lore:
- - ""
- - "&b&k|&b- &7&o私の運はどうですかね..."
- - "&b&k|&b- &e&o鑑定機は &7&oこの属性をランダムに与えます..."
- guard_sword:
- name: "&6ガーディアンの剣"
- lore:
- - ""
- - "&b&k|&b- &7&o最期までお守りします"
- - ""
- peach_sword:
- name: "&6桃の木の剣"
- lore:
- - ""
- - "&b&k|&b- &7&o古典的なゾンビ映画へのオマージュ..."
- - ""
- soul_sword:
- name: "&6魂の剣"
- lore:
- - ""
- - "&b&k|&b- &7&oこの剣に悪魔の魂がつぎ込まれた..."
- - "&b&k|&b- &e&o右クリック &7&oしてうなりだす..."
- - "&b&k|&b- &e&o満腹度&7&oを &e&o体力&7&oに変える..."
- - ""
- sky_sword:
- name: "&6天滅の剣"
- lore:
- - ""
- - "&b&k|&b- &7&o天滅、なんと強烈な名称だ..."
- - "&b&k|&b- &e&o右クリック &7&oして空に突進..."
- - ""
- devil_sword:
- name: "&6魔殺の剣"
- lore:
- - ""
- - "&b&k|&b- &7&o魔殺、なんと偉大な名称だ..."
- - "&b&k|&b- &e&o右クリック &7&oして聖火を用いて、暗闇を残らず焼き尽くす"
- - ""
- sky_devil_sword:
- name: "&6天滅魔殺の剣"
- lore:
- - ""
- - "&b&k|&b- &7&o天滅と魔殺は次々に強大なエネルギーを発する..."
- - "&b&k|&b- &e&o右クリック &7&oして前にドラゴンブレスを三つ連射して、自分を強化します..."
- - ""
-lores:
- per-use: "&7毎回使用"
- not-appraised: "&b&k|&b- &7&oまだ鑑定されていない"
- appraised: "&b&k|&b- &7&o鑑定された &b| &dレベル&e&l{0}"
- click-to-open: "&7\u21E8 &aクリックして開く"
- any-random-equipment: "&f任意のランダムな装備"
-recipes:
- compressor_mock:
- name: "&b圧縮機"
- lore:
- - "&7このアイテムは表示されたように"
- - "&7圧縮機にクラフトされています"
-researches:
- food: "Bumpの食品"
- random_equipment: "ランダムな装備"
- appraise: "鑑定"
- stuff: "魔法の物"
- old_stuff: "金を獲得"
- bow: "Bumpの弓"
- peach_sword: "桃の木の剣"
- normal_sword: "普通の剣"
- soul_sword: "魂の剣"
- sky_devil: "天滅魔殺"
-messages:
- no-permission: "&c権限がありません。"
- no-input: "&cアイテムを入れてください。"
- output-no-space: "&c出力の空間が足りない!"
- not-enough-power: "&cエネルギーが足りない!"
- stacked: "&c積み重ねたものは使えません"
- legacy: "&c古いアイテムを使用しています。新しいアイテムにアップグレードする必要があります。"
- deprecated: "&c廃止予定のアイテムを使用してます。近日中に消除されます。"
- click-here: "&eここをクリック:"
- food:
- cooldown: "&b&k|&b- &7&oこれをまた食べるにはしばらく待つ必要があります!"
- xuebi: "&b&k|&b- &7&o涼しい夏!"
- kele: "&b&k|&b- &7&oデブオタクの勝利!"
- fangbianmian: "&b&k|&b- &7&o子供時代の味!"
- latiao: "&b&k|&b- &7&oもう十分辛い!"
- kouxiangtang: "&b&k|&b- &7&o幼年時代の味!"
- zongzi: "&b&k|&b- &7&o味は甘いですか?それともしょっぱいですか?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG、金だ..."
- appraisal_paper:
- legacy: "&b古い品質鑑定符がアップグレードされました。"
- invalid: "&cこのアイテムは鑑定できさせない!"
- success: "&a今はこのアイテムが鑑定できさせます!"
- weapon:
- unavailable: "&b&k|&b- &7&o現在このスキルは使用できません!"
- low-food-level: "&b&k|&b- &7&o満腹度を体力に変える量は不足しています!"
- cooldown: "&b&k|&b- &7&o武器の技能をまた使えるにはしばらく待つ必要があります!"
- soul_sword:
- converted-part: "&b&k|&b- &7&o一部の満腹度は体力に変えました!"
- converted-all: "&b&k|&b- &7&oすべての満腹度は体力に変えました!"
- devil_sword: "&b&k|&b- &7&o魔殺、天から裁けよ!"
- sky_sword:
- activated: "&b&k|&b- &7&o天滅、天まで飛びせよ!"
- protected: "&b&k|&b- &7&o天滅の剣はあなたを落下ダメージから守りました"
- sky_devil_sword:
- activated: "&b&k|&b- &7&o魔殺と天滅、正義をもたらす!"
- deactivated: "&b&k|&b- &7&o強化の時間が終了しました!"
- light_bow: "&b&k|&b- &7&o天罰!"
- wither_skull_bow: "&b&k|&b- &7&o衰弱!"
- machine:
- appraisal:
- invalid: "&cこのアイテムはまだ鑑定されていない!"
- not-accepted: "&ck現在の鑑定タイプはこのアイテムを受け付けられません!"
- appraised: "&cアイテムがもう鑑定されたので、また鑑定させるのはできない!"
- success: "&a鑑定成功!"
- attribute-grindstone:
- invalid: "&cこのアイテムはまだ鑑定していません!"
- success: "&a鑑定結果が排除されました!"
-console:
- loading-appraise-types: "設定ファイルから鑑定タイプを読み込み中。"
- loading-appraise-type: "鑑定タイプ「{0}」を読み込み中"
- disabled-appraise-type: "鑑定タイプ「{0}」が無効されているので、無視しています。"
- loaded-appraise-type: "鑑定タイプ「{0}」を読み込みました。"
- error-loading-appraise-type: "鑑定タイプ「{0}」を読み込み中にエラーが発生しました:{1}"
- missing-appraise-stars: "設定に「appraise.stars」の部分が欠けています。"
- use-default-appraise-stars: "デフォルトの鑑定星設定を使用しています。"
- invalid-appraise-stars: "鑑定星は0から127までしか設定できません!"
- error-sound: "音の設定ファイルを読み込み中にエラーが発生しました:{0}"
- invalid-sound-config: "BumpSound: {0} の設定が見つかれません"
- invalid-sound-volume: "BumpSound「{0}」の無効な音量:{1} ({2}以上でなければならない)"
- invalid-sound-pitch: "BumpSound「{0}」の無効な音高:{1} ({2}以上でなければならない)"
-gui:
- appraise:
- name: "&eクリックして鑑定する"
- lore:
- - "&7<- 鑑定したいアイテムを左側に入れてください"
- - "&eここにクリックして鑑定する"
- appraise_type_selector:
- name: "&b現在のタイプ:&e{0}"
- lore:
- - ""
- - "&7Bumpのカテゴリーに詳細を表示する"
- - "&eクリックしてこのタイプを選択します"
- appraise_type_selector_menu:
- title: "&6鑑定タイプ選択"
- lore:
- - ""
- - "&eクリックしてこのタイプを選択します"
- appraisal_paper:
- name: "&eクリックして適用する"
- lore:
- - "&7<- アイテムを左側に入れてください"
- - "&7アイテムの鑑定を許可するには、ここをクリックしてください"
- grind:
- name: "&eクリックして属性を排除する"
- lore:
- - "&7<- 鑑定されたアイテムを左側においてください。"
- - "&7ここをクリックして属性を排除する"
-appraise_info:
- name: "&b鑑定タイプ:&e{0}"
- click: "&eクリックして詳細表示"
- equipment_type:
- name: "&a該当の装備タイプ:&b{0}"
- any: "&7任意なアイテム"
- vanilla: "&7原版アイテムのみ"
- slimefun: "&7Slimefunアイテムのみ"
- material:
- name: "&a装備の材料をチェック: &b{0}"
- lore_enabled:
- - "&7以下のアイテムのみが受け入れられます:"
- lore_enabled_more: "&7後は{0}つ…"
- lore_disabled:
- - "&7アイテムの材料はチェックされません。"
- equipment_slot:
- name: "&a装備スロット"
- lore:
- - "&7属性を与えます"
- - "&7装備スロットへ:"
- attribute:
- name: "&e属性:&9{0}"
- range: "&7範囲:&b{0} &7~ &b{1}"
- weight: "&7重量:&b{0}%"
-
diff --git a/src/main/resources/lang/nl-NL.yml b/src/main/resources/lang/nl-NL.yml
deleted file mode 100644
index 0072e1fb..00000000
--- a/src/main/resources/lang/nl-NL.yml
+++ /dev/null
@@ -1,145 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Bepantsering"
- food: "&bBump - Voedsel"
- machine: "&bBump - Machines"
- stuff: "&bBump - Spullen"
- tool: "&bBump - Gereedschap"
- weapon: "&bBump - Magisch Wapen"
-items:
- random_helmet:
- name: "&6Willekeurige Helm"
- lore:
- - ""
- - "&b&k|&b- &7&oHoe is mijn geluk..."
- - "&b&k|&b- &e&o De beoordeler &7&ogeeft deze eigenschap willekeurig..."
- random_horse_armor:
- name: "&6Willekeurig Paarden Harnas"
- lore:
- - ""
- - "&b&k|&b- &7&oHoe is mijn geluk..."
- - "&b&k|&b- &e&o De beoordeler &7&ogeeft deze eigenschap willekeurig..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&kub- &b- Zeer zoet en zoet, nog steeds aan het bubbelen!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&kuit &b- Het ijs zit vol met kracht, en als je het drinkt, kun je vliegen!"
- - ""
- fangbianmian:
- name: "&eMaster Kong onmiddellijke noodle"
- lore:
- - ""
- - "&b&k|&b- Deze smaak is pittig!!"
- - ""
- latiao:
- name: "&ePittige gluten"
- lore:
- - ""
- - "&b&k- &b- Cool! Ik vergeet nog steeds niet om de pittige olie te likken na het eten..."
- - ""
- kouxiangtang:
- name: "&eKauwgom"
- lore:
- - ""
- - "&b&km &b- Erg plakkerig..."
- - ""
- appraisal:
- name: "&bBeoordelings instrument"
- lore:
- - ""
- - "&c&k|&7- Oh! Een defect toestel..."
- - ""
- sun_energy:
- name: "&ePhotosynthetische energie"
- lore:
- - ""
- - "&b&km &b- Gemuteerde planten zullen ook aan fotosynthese doen..."
- - ""
- mecha_gear:
- name: "&eMechanische uitrusting"
- lore:
- - ""
- - "&b&k|&b- Iets geëlimineerd door een grote fabriek..."
- - ""
- old_coin:
- name: "&eGebroken Gouden Munt"
- lore:
- - ""
- - "&b&k|&b- Wat kan ik kopen..."
- - ""
- make:
- name: "&eComputer Technologie Kern"
- lore:
- - ""
- - "&b&k|&b- waar wordt het voor gebruikt..."
- - ""
- old_cpu:
- name: "&eGebroken CPU"
- lore:
- - ""
- - "&b&k|&b- van welke computer werd het verwijderd..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- Intact..."
- - ""
- soul_paper:
- name: "&eZiel Talisman"
- lore:
- - ""
- - "&b&k|&b- De kracht van de ziel"
- - ""
- ksf_stuff:
- name: "&eInstant Noodle Seizoen"
- lore:
- - ""
- - "&b&k|&b- Sizzle~ Het is pittig"
- - ""
- water_sugar:
- name: "&eSoda Snoep"
- lore:
- - ""
- - "&b&k|&b- Sprite? Of Coca-Cola?"
- - ""
- peach_wood:
- name: "&ePerzik Hout"
- lore:
- - ""
- - "&b&k|&b-Toevlucht voor boze geesten"
- - ""
- update_power:
- name: "&eUpgrade Kern"
- lore:
- - ""
- - "&b&k|&b- Gebruikt om wat rare voorwerpen te upgraden..."
- - ""
- getgold_spade:
- name: "&eKrijgen-gouden schep"
- lore:
- - ""
- - "&b&k|&b- Er is een zekere kans om gebroken gouden munten in het zand uit te graven!"
- - ""
- appraisal_paper_armor:
- name: "&eHarnas Kwaliteit identificator"
- lore:
- - ""
- - "&b&k|&b- Een willekeurig harnas attribuut voor een bepaald voorwerp!"
- - ""
- - ""
-messages:
- not-enough-power: "Niet genoeg energie."
- food:
- xuebi: "&b&k|&b- &7&oA coole zomer!!"
- kele: "&b&k|&b- &7&oDe overwinning van de vette otaku!"
- fangbianmian: "&b&k|&b- &7&oDe smaak van de kindertijd!"
- latiao: "&b&k|&b- &7&oDit is pittig genoeg!"
-
diff --git a/src/main/resources/lang/pt-BR.yml b/src/main/resources/lang/pt-BR.yml
deleted file mode 100644
index 3d41ecfd..00000000
--- a/src/main/resources/lang/pt-BR.yml
+++ /dev/null
@@ -1,286 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Armaduras"
- food: "&bBump - Comidas"
- machine: "&bBump - Maquinas"
- stuff: "&bBump - Outros"
- tool: "&bBump - Ferramentas"
- weapon: "&bBump - Armas Mágicas"
-items:
- random_helmet:
- name: "&6Capacete Aleatório"
- lore:
- - ""
- - "&b&k|&b- &7&oComo está minha sorte..."
- - "&b&k|&b- &e&oO avaliador &7&oaleatoriamente dá esse atributo..."
- random_horse_armor:
- name: "&6Armadura de Cavalo Aleatória"
- lore:
- - ""
- - "&b&k|&b- &7&oComo está minha sorte..."
- - "&b&k|&b- &e&oO avaliador &7&oaleatoriamente dá esse atributo..."
- xuebi:
- name: "&6Sprite"
- lore:
- - ""
- - "&b&k|&b- Muito doce e doce, ainda borbulhando!"
- - ""
- kele:
- name: "&eCola"
- lore:
- - ""
- - "&b&k|&b- O gelo está cheio de força e, se você o beber, poderá voar!"
- - ""
- fangbianmian:
- name: "&eMiojo"
- lore:
- - ""
- - "&b&k|&b- Esse sabor é picante!!"
- - ""
- latiao:
- name: "&eGlúten picante"
- lore:
- - ""
- - "&b&k|&b- Legal! Ainda não esqueço de lamber o óleo picante depois de comer..."
- - ""
- kouxiangtang:
- name: "&eGoma de mascar"
- lore:
- - ""
- - "&b&k|&b- Muito pegajoso..."
- - ""
- zongzi:
- name: "&aZongzi"
- lore:
- - ""
- - "&b&k|&b- Feliz festival do navio do dragão!"
- - ""
- appraisal:
- name: "&bInstrumento de avaliação"
- lore:
- - ""
- - "&c&k|&7- Oh! Um instrumento defeituoso..."
- - ""
- sun_energy:
- name: "&eEnergia fotossintética"
- lore:
- - ""
- - "&b&k|&b- Plantas mutantes também irão fotossintetizar..."
- - ""
- mecha_gear:
- name: "&eEngrenagem Mecânica"
- lore:
- - ""
- - "&b&k|&b- Algo eliminado por uma grande fábrica..."
- - ""
- old_coin:
- name: "&eMoeda de ouro quebrada"
- lore:
- - ""
- - "&b&k|&b- O que posso comprar..."
- - ""
- make:
- name: "&eNúcleo de Tecnologia da Computação"
- lore:
- - ""
- - "&b&k|&b- Para que isso é usado..."
- - ""
- old_cpu:
- name: "&eCPU quebrada"
- lore:
- - ""
- - "&b&k|&b- De qual computador foi removido..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- Intacto..."
- - ""
- soul_paper:
- name: "&eTalismã da Alma"
- lore:
- - ""
- - "&b&k|&b- O poder da alma"
- - ""
- ksf_stuff:
- name: "&eTempero Instantâneo de Macarrão"
- lore:
- - ""
- - "&b&k|&b- Sizzle~ É picante"
- - ""
- water_sugar:
- name: "&eRefrigerante Doce"
- lore:
- - ""
- - "&b&k|&b- Sprite? ou Coca-Cola?"
- - ""
- peach_wood:
- name: "&eMadeira de Mogno"
- lore:
- - ""
- - "&b&k|&b- Refúgio de espíritos malignos"
- - ""
- update_power:
- name: "&eNúcleo de atualização"
- lore:
- - ""
- - "&b&k|&b- Usado para atualizar alguns itens estranhos..."
- - ""
- getgold_spade:
- name: "&ePá de ouro"
- lore:
- - ""
- - "&b&k|&b- Há uma certa chance de desenterrar moedas de ouro quebradas na areia!"
- - ""
- appraisal_paper_armor:
- name: "&eIdentificador de Qualidade de Armadura"
- lore:
- - ""
- - "&b&k|&b- Um atributo de armadura aleatório para um determinado item!"
- - "&b&k|&b- Muito caro, certifique-se de mantê-lo..."
- - ""
- appraisal_paper_damage:
- name: "&eIdentificador de Qualidade da Arma"
- lore:
- - ""
- - "&b&k|&b- Um atributo de ataque aleatório para um determinado item!"
- - "&b&k|&b- Muito caro, certifique-se de mantê-lo..."
- - ""
- appraisal_paper_horse_armor:
- name: "&eIdentificador de Qualidade de Armadura de Cavalo"
- lore:
- - ""
- - "&b&k|&b- Um atributo de armadura aleatório para um determinado item!"
- - "&b&k|&b- Muito caro, certifique-se de mantê-lo..."
- - ""
- light_bow:
- name: "&6Arco de punição de Deus"
- lore:
- - ""
- - "&b&k|&b- &7&oAceite o castigo de Deus..."
- - ""
- witherskull_bow:
- name: "&6Arco Corrumpido"
- lore:
- - ""
- - "&b&k|&b- &7&oO que ele lança é tudo que for morto..."
- - ""
- emer_sword:
- name: "&6Espada de Esmeralda"
- lore:
- - ""
- - "&b&k|&b- &7&oFeito de esmeraldas caras..."
- - ""
- bone_sword:
- name: "&6Espada de Osso"
- lore:
- - ""
- - "&b&k|&b- &7&oMuito difícil..."
- - ""
- random_sword:
- name: "&6Lâmina curta aleatória"
- lore:
- - ""
- - "&b&k|&b- &7&oComo está minha sorte..."
- - "&b&k|&b- &e&oO avaliador &7&oaleatoriamente dá este atributo..."
- guard_sword:
- name: "&6Espada do Guardião"
- lore:
- - ""
- - "&b&k|&b- &7&oEu vou te guardar até o último momento da vida"
- - ""
- peach_sword:
- name: "&6Espada de Madeira de Mogno"
- lore:
- - ""
- - "&b&k|&b- &7&oHomenagem ao clássico filme de zumbi..."
- - ""
- soul_sword:
- name: "&6Espada das Almas"
- lore:
- - ""
- - "&b&k|&b- &7&oA alma do diabo é injetada aqui..."
- - "&b&k|&b- &e&oBotão Direito &7&opara fazer um crescimento baixo..."
- - "&b&k|&b- &7&oTransforme &7&osua &e&osaciedade &7&oem &e&osaúde&7&o..."
- - ""
- sky_sword:
- name: "&6Espada de Ruptura do Céu"
- lore:
- - ""
- - "&b&k|&b- &7&oRuptura do Céu, que nome dominador..."
- - "&b&k|&b- &e&oBotão direito &7&oe correr para o céu..."
- - ""
- devil_sword:
- name: "&6Espada Matadora de Demônios"
- lore:
- - ""
- - "&b&k|&b- &7&oMatadora de Demônios, que título poderoso..."
- - "&b&k|&b- &e&oBotão direito &7&opara enviar o fogo sagrado para varrer todas as trevas..."
- - ""
- sky_devil_sword:
- name: "&6Espada Desintegrada do Demônio Celestial"
- lore:
- - ""
- - "&b&k|&b- &7&oRuptura do céu e cortando o diabo, um após o outro emite uma energia poderosa..."
- - ""
- - ""
-lores:
- per-use: "&7por uso"
- not-appraised: "&b&k|&b- &7&oNão avaliado"
- appraised: "&b&k|&b- &7&oAvaliado &b| &dLevel: &e&l{0}"
-researches:
- food: "Bomba de comida"
- random_equipment: "Equipamento aleatório"
- appraise: "Apreciar"
- stuff: "Itens mágicos"
- old_stuff: "Obtendo ouro"
- bow: "Carregar arcos"
- peach_sword: "Espada de mogno"
- normal_sword: "Espada normal"
- soul_sword: "Espada da Alma"
- sky_devil: "Céu ou Demônio"
-messages:
- no-input: "&cPor favor, coloque os itens."
- output-no-space: "&cSem espaço!"
- not-enough-power: "&cNão há energia suficiente."
- stacked: "&cVocê não pode usar este item quando está empilhado."
- food:
- xuebi: "&b&k|&b- &7&oUm verão fresco!!"
- kele: "&b&k|&b- &7&oA vitória do otaku!"
- fangbianmian: "&b&k|&b- &7&oO sabor da infância!"
- latiao: "&b&k|&b- &7&oIsso é picante o suficiente!"
- kouxiangtang: "&b&k|&b- &7&oEspírito de fada vibrando!"
- zongzi: "&b&k|&b- &7&oDoce ou salgado?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG, ouro..."
- appraisal_paper:
- invalid: "&cEste item é não pode ser avaliado!"
- success: "&aEste item pode ser avaliado agora!"
- weapon:
- unavailable: "&b&k|&b- &7&oVocê não pode ativar esta habilidade agora!"
- low-food-level: "&b&k|&b- &7&oSeu nível de alimentação não é suficiente para converter sua saúde!"
- soul_sword:
- converted-part: "&b&k|&b- &7&oParte do seu nível alimentar foi convertido em saúde!"
- converted-all: "&b&k|&b- &7&oTodo o seu nível de comida foi convertido em saúde!"
- devil_sword: "&b&k|&b- &7&oMatador de demônios, traga justiça do céu!"
- light_bow: "&b&k|&b- &7&oDeus castiga!"
- wither_skull_bow: "&b&k|&b- &7&oDecompondo!"
- machine:
- appraisal:
- invalid: "&cO item não suporta ser avaliado!"
- appraised: "&cDesculpe, o item não pode ser identificado ou já foi avaliado!"
- success: "&aAvaliação!"
-gui:
- appraise:
- name: "&eClique para avaliar"
- lore:
- - "&7<- Coloque os itens a serem avaliados no lado esquerdo"
- - "&7Clique aqui para avaliar"
- appraisal_paper:
- name: "&eClique para aplicar"
- lore:
- - "&7<- Coloque os itens do lado esquerdo"
- - "&7Clique aqui para permitir que o item seja avaliado"
-
diff --git a/src/main/resources/lang/ru-RU.yml b/src/main/resources/lang/ru-RU.yml
deleted file mode 100644
index d6577625..00000000
--- a/src/main/resources/lang/ru-RU.yml
+++ /dev/null
@@ -1,286 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - доспех"
- food: "&bBump - Еда"
- machine: "&bBump - Машина"
- stuff: "&bBump - Вещь"
- tool: "&bBump - Инструмент"
- weapon: "&bBump - Магическое оружие"
-items:
- random_helmet:
- name: "&6Случайные шлемы"
- lore:
- - ""
- - "&b&k|&b- &7&oКак моя удача..."
- - "&b&k|&b- &e&оценщик &7&orandomly дает этот атрибут..."
- random_horse_armor:
- name: "&6Случайный Макей"
- lore:
- - ""
- - "&b&k|&b- &7&oКак моя удача..."
- - "&b&k|&b- &e&оценщик &7&orandomly дает этот атрибут..."
- xuebi:
- name: "&6Спрайт"
- lore:
- - ""
- - "&b&k|&b- Очень сладкий, и с пузырьками!"
- - ""
- kele:
- name: "&eКола"
- lore:
- - ""
- - "&b&k|&b- Лед полон сил, и если вы выпьете его, вы можете летать!"
- - ""
- fangbianmian:
- name: "&eМастер Кан лапша быстрого приготовления"
- lore:
- - ""
- - "&b&k|&b- Его вкус пряный!!"
- - ""
- latiao:
- name: "&eПряный глютен"
- lore:
- - ""
- - "&b&k|&b- Круто! Я до сих пор не забываю залить пряное масло после еды..."
- - ""
- kouxiangtang:
- name: "&eЖвачка"
- lore:
- - ""
- - "&b&k|&b- рот очень липкий..."
- - ""
- zongzi:
- name: "&aпельмени"
- lore:
- - ""
- - "&b&k|&b- С праздником лодок - драконов!"
- - ""
- appraisal:
- name: "&bАттестационные приборы"
- lore:
- - ""
- - "&c&k|&7- Ой! Это остаточный дефектный продукт..."
- - ""
- sun_energy:
- name: "&eфотосинтетическая энергия"
- lore:
- - ""
- - "&b&k|&b- Вариационные растения также могут использоваться для фотосинтеза..."
- - ""
- mecha_gear:
- name: "&eМеханическая шестерня"
- lore:
- - ""
- - "&b&k|&b- То, что было ликвидировано на крупном заводе..."
- - ""
- old_coin:
- name: "&eПоврежденные золотые монеты"
- lore:
- - ""
- - "&b&k|&b- Что можно купить за эту штуку..."
- - ""
- make:
- name: "&eядро компьютерных технологий"
- lore:
- - ""
- - "&b&k|&b- Какова его роль..."
- - ""
- old_cpu:
- name: "&eПоврежденный ЦП"
- lore:
- - ""
- - "&b&k|&b- С какого компьютера снять..."
- - ""
- cpu:
- name: "&eЦП"
- lore:
- - ""
- - "&b&k|&b- Исправность..."
- - ""
- soul_paper:
- name: "&eДушевая руна"
- lore:
- - ""
- - "&b&k|&b- Была привита сила души"
- - ""
- ksf_stuff:
- name: "&eприправа лапши быстрого приготовления"
- lore:
- - ""
- - "&b&k|&b- пиццел~ Это пряный вкус"
- - ""
- water_sugar:
- name: "&eСода Конфеты"
- lore:
- - ""
- - "&b&k|&b- спрайт? Кола?"
- - ""
- peach_wood:
- name: "&eПерсиковые деревья"
- lore:
- - ""
- - "&b&k|&b- Зло идти трудно"
- - ""
- update_power:
- name: "&eОбновить ядро"
- lore:
- - ""
- - "&b&k|&b- Используется для улучшения странных элементов..."
- - ""
- getgold_spade:
- name: "&eДревние золотые лопаты"
- lore:
- - ""
- - "&b&k|&b- В песке есть определенная вероятность выкапывать поврежденные золотые монеты!"
- - ""
- appraisal_paper_armor:
- name: "&eИдентификатор качества брони"
- lore:
- - ""
- - "&b&k|&b- Атрибут случайной брони для данного предмета!"
- - "&b&k|&b- Очень дорогой, не забудьте держать его..."
- - ""
- appraisal_paper_damage:
- name: "&eИдентификатор качества оружия"
- lore:
- - ""
- - "&b&k|&b- Характеристики случайной атаки для данного предмета!"
- - "&b&k|&b- Очень дорогой, не забудьте держать его..."
- - ""
- appraisal_paper_horse_armor:
- name: "&eИдентификатор качества конской брони"
- lore:
- - ""
- - "&b&k|&b- Атрибут случайной брони для данного предмета!"
- - "&b&k|&b- Очень дорогой, не забудьте держать его..."
- - ""
- light_bow:
- name: "&6Божественный Лук Наказания"
- lore:
- - ""
- - "&b&k|&b- &7&oПринять Божье наказание..."
- - ""
- witherskull_bow:
- name: "&6Дуги увядают"
- lore:
- - ""
- - "&b&k|&b- &7&oОн излучает каждую смерть..."
- - ""
- emer_sword:
- name: "&6Изумрудный меч"
- lore:
- - ""
- - "&b&k|&b- &7&oСделано из дорогих изумрудов..."
- - ""
- bone_sword:
- name: "&6Костный меч"
- lore:
- - ""
- - "&b&k|&b- &7&oОчень жестко..."
- - ""
- random_sword:
- name: "&6Случайный короткий меч"
- lore:
- - ""
- - "&b&k|&b- &7&oКак моя удача..."
- - "&b&k|&b- &e&оценщик &7&orandomly дает этот атрибут..."
- guard_sword:
- name: "&6Меч Стража"
- lore:
- - ""
- - "&b&k|&b- &7&oI будет охранять вас до последнего момента жизни"
- - ""
- peach_sword:
- name: "&6Персиковый меч"
- lore:
- - ""
- - "&b&k|&b- &7&oОтдайте должное классическому фильму зомби..."
- - ""
- soul_sword:
- name: "&6Меч Души"
- lore:
- - ""
- - "&b&k|&b- &7&oДуша дьявола вводится здесь..."
- - "&b&k|&b- &e&oПравой кнопкой мыши &7&oСделайте низкий рев..."
- - "&b&k|&b- &7&oПреобразуйте свое значение голода в значение жизни..."
- - ""
- sky_sword:
- name: "&6Тяжелый меч"
- lore:
- - ""
- - "&b&k|&b- &7&oКакое ослепительное имя..."
- - "&b&k|&b- &e&oправое нажатие &7&oи спешится на небо..."
- - ""
- devil_sword:
- name: "&6Меч Следопыта демона"
- lore:
- - ""
- - "&b&k|&b- &7&oДемон Следопыт, как его звание..."
- - "&b&k|&b- &e&oправый клик &7&oчтобы отправить священный огонь для полного темноты..."
- - ""
- sky_devil_sword:
- name: "&6Небесный демоновый меч"
- lore:
- - ""
- - "&b&k|&b- &7&obreak неба и разрезание дьявола, один за другим, выделяет мощную энергию..."
- - ""
- - ""
-lores:
- per-use: "&7Каждый раз использовать"
- not-appraised: "&b&k|&b- &7&oНе оценено"
- appraised: "&b&k|&b- &7&oПодсчитано &b| &dЗвезды: &e&l{0}"
-researches:
- food: "Bump еды"
- random_equipment: "Случайное снаряжение"
- appraise: "Экспертиза"
- stuff: "Магическая вещь"
- old_stuff: "Получение золота"
- bow: "Bump Арбалет"
- peach_sword: "Персиковый меч"
- normal_sword: "Обычный меч"
- soul_sword: "Меч Души"
- sky_devil: "Небесный или демон"
-messages:
- no-input: "&cПожалуйста поместите элементы."
- output-no-space: "&cНет места для вывода!"
- not-enough-power: "&cНедостаточно электроэнергии."
- stacked: "&cЭтот элемент нельзя использовать в стеке."
- food:
- xuebi: "&b&k|&b- &7&oПрохладное лето!!"
- kele: "&b&k|&b- &7&oПобеда жира оттасу!"
- fangbianmian: "&b&k|&b- &7&oвкус детства!"
- latiao: "&b&k|&b- &7&oЭто достаточно острых!"
- kouxiangtang: "&b&k|&b- &7&oFairy дух пылает!"
- zongzi: "&b&k|&b- &7&oСладкие или соленые?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG, золото..."
- appraisal_paper:
- invalid: "&cЭтот элемент не оценен!"
- success: "&aТеперь можно оценить этот элемент!"
- weapon:
- unavailable: "&b&k|&b- &7&oВы не можете активировать этот навык!"
- low-food-level: "&b&k|&b- &7&oВаш уровень еды недостаточно для преобразования здоровья!"
- soul_sword:
- converted-part: "&b&k|&b- &7&oЧасть еды была преобразована в здоровье!"
- converted-all: "&b&k|&b- &7&oВесь ваш уровень еды был преобразован в здоровье!"
- devil_sword: "&b&k|&b- &7&oДемон Следопыт, прими правосудие с неба!"
- light_bow: "&b&k|&b- &7&oБог наказает!"
- wither_skull_bow: "&b&k|&b- &7&oБог наказает!"
- machine:
- appraisal:
- invalid: "&cТовар не поддерживает оценку!"
- appraised: "&cИзвините, что элемент не может быть идентифицирован или уже оценен!"
- success: "&aОценка!"
-gui:
- appraise:
- name: "&eНажмите, чтобы оценить"
- lore:
- - "&7<- Поместить элементы для оценки с левой стороны"
- - "&7Нажмите здесь, чтобы оценить"
- appraisal_paper:
- name: "&eНажмите, чтобы применить"
- lore:
- - "&7<- Поместить элементы с левой стороны"
- - "&7Нажмите здесь, чтобы дать возможность оценивать элемент"
-
diff --git a/src/main/resources/lang/sk-SK.yml b/src/main/resources/lang/sk-SK.yml
deleted file mode 100644
index cd21505a..00000000
--- a/src/main/resources/lang/sk-SK.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-
diff --git a/src/main/resources/lang/tr-TR.yml b/src/main/resources/lang/tr-TR.yml
deleted file mode 100644
index 28a4ce8f..00000000
--- a/src/main/resources/lang/tr-TR.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - Zırh"
- food: "&bBump - Yemek"
- machine: "&bBump - Makine"
- stuff: "&bBump - Eşyalar"
- tool: "&bBump - Aletler"
- weapon: "&bBump - Büyülü Silahlar"
-items:
- random_helmet:
- name: "&6Rastgele Kask"
- lore:
- - ""
- - "&b&k|&b- &7&oŞansım nasıl..."
- - ""
- random_horse_armor:
- name: "&6Rastgele At Zırhı"
-
diff --git a/src/main/resources/lang/zh-CL.yml b/src/main/resources/lang/zh-CL.yml
deleted file mode 100644
index cd21505a..00000000
--- a/src/main/resources/lang/zh-CL.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-
diff --git a/src/main/resources/lang/zh-CN.yml b/src/main/resources/lang/zh-CN.yml
deleted file mode 100644
index ef195f45..00000000
--- a/src/main/resources/lang/zh-CN.yml
+++ /dev/null
@@ -1,385 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - 护甲"
- food: "&bBump - 食物"
- machine: "&bBump - 机器"
- stuff: "&bBump - 魔法物品"
- tool: "&bBump - 工具"
- weapon: "&bBump - 魔法武器"
- appraise_info: "&eBump - 鉴定类型信息"
- wiki: "&eBump - Wiki"
-items:
- random_helmet:
- name: "&6随机头盔"
- lore:
- - ""
- - "&b&k|&b- &7&o我的运气怎么样..."
- - "&b&k|&b- &e&o鉴定仪 &7&o随机给予此一个属性..."
- random_horse_armor:
- name: "&6随机马铠"
- lore:
- - ""
- - "&b&k|&b- &7&o我的运气怎么样..."
- - "&b&k|&b- &e&o鉴定仪 &7&o随机给予此一个属性..."
- xuebi:
- name: "&6雪碧"
- lore:
- - ""
- - "&b&k|&b- 很甜很甜,还冒着气泡!"
- - ""
- kele:
- name: "&e可乐"
- lore:
- - ""
- - "&b&k|&b- 冰力十足,喝了真精神,还会飞呢!"
- - ""
- fangbianmian:
- name: "&e康师傅方便面"
- lore:
- - ""
- - "&b&k|&b- 这个味,对辣!"
- - ""
- latiao:
- name: "&e辣条"
- lore:
- - ""
- - "&b&k|&b- 爽,吃了之后还不忘舔舔辣油..."
- - ""
- kouxiangtang:
- name: "&e口香糖"
- lore:
- - ""
- - "&b&k|&b- 很粘稠的..."
- - ""
- zongzi:
- name: "&a粽子"
- lore:
- - ""
- - "&b&k|&b- 端午节快乐!"
- - ""
- appraisal:
- name: "&b鉴定仪"
- lore:
- - ""
- - "&c&k|&7- 哦,你这是个残次品..."
- - ""
- attribute_grindstone:
- name: "&b属性砂轮"
- lore:
- - ""
- - "&c&k|&7- 它可以清除属性..."
- - ""
- sun_energy:
- name: "&e光合能量"
- lore:
- - ""
- - "&b&k|&b- 变异的植物也会进行光合作用..."
- - ""
- mecha_gear:
- name: "&e机械齿轮"
- lore:
- - ""
- - "&b&k|&b- 某大型工厂淘汰下来的东西..."
- - ""
- old_coin:
- name: "&e破损的的金币"
- lore:
- - ""
- - "&b&k|&b- 这东西能买什么..."
- - ""
- make:
- name: "&e计算机工艺核心"
- lore:
- - ""
- - "&b&k|&b- 它用来干什么呢..."
- - ""
- old_cpu:
- name: "&e破损的CPU"
- lore:
- - ""
- - "&b&k|&b- 从哪家的电脑上拆下来的..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- 完好无损..."
- - ""
- soul_paper:
- name: "&e灵魂之符"
- lore:
- - ""
- - "&b&k|&b- 被注入了灵魂的力量"
- - ""
- ksf_stuff:
- name: "&e方便面调料"
- lore:
- - ""
- - "&b&k|&b- 嘶~ 是香辣味的"
- - ""
- water_sugar:
- name: "&e汽水糖"
- lore:
- - ""
- - "&b&k|&b- 雪碧? 还是可口可乐?"
- - ""
- peach_wood:
- name: "&e桃木"
- lore:
- - ""
- - "&b&k|&b- 驱邪避难"
- - ""
- update_power:
- name: "&e升级核心"
- lore:
- - ""
- - "&b&k|&b- 用来升级一些奇怪的物品..."
- - ""
- compressed_random_equipment:
- name: "&e压缩的随机装备"
- lore:
- - ""
- - "&b&k|&b- 好像不能再使用了..."
- - ""
- getgold_spade:
- name: "&e摸金铲"
- lore:
- - ""
- - "&b&k|&b- 在沙子里一定几率挖出破损的金币!"
- - ""
- quality_identifier:
- name: "&e品质鉴定符"
- lore:
- - ""
- - "&b&k|&b- 为可用的物品添加随机属性!"
- - "&b&k|&b- 非常昂贵,一定要保存好..."
- - ""
- appraisal_paper_armor:
- name: "&e护甲品质鉴定符"
- lore:
- - ""
- - "&b&k|&b- 给定物品随机一个护甲属性!"
- - "&b&k|&b- 非常昂贵,一定要保存好..."
- - ""
- appraisal_paper_damage:
- name: "&e武器品质鉴定符"
- lore:
- - ""
- - "&b&k|&b- 给定物品随机一个攻击属性!"
- - "&b&k|&b- 非常昂贵,一定要保存好..."
- - ""
- appraisal_paper_horse_armor:
- name: "&e马铠品质鉴定符"
- lore:
- - ""
- - "&b&k|&b- 给定物品随机一个护甲属性!"
- - "&b&k|&b- 非常昂贵,一定要保存好..."
- - ""
- light_bow:
- name: "&6神罚之弓"
- lore:
- - ""
- - "&b&k|&b- &7&o接受神的惩罚..."
- - ""
- witherskull_bow:
- name: "&6凋零弓"
- lore:
- - ""
- - "&b&k|&b- &7&o它发射出去的的是每一个亡灵..."
- - ""
- emer_sword:
- name: "&6绿宝石之剑"
- lore:
- - ""
- - "&b&k|&b- &7&o昂贵的绿宝石打造而成..."
- - ""
- bone_sword:
- name: "&6骨剑"
- lore:
- - ""
- - "&b&k|&b- &7&o坚硬无比..."
- - ""
- random_sword:
- name: "&6随机短刃"
- lore:
- - ""
- - "&b&k|&b- &7&o我的运气怎么样..."
- - "&b&k|&b- &e&o鉴定仪 &7&o随机给予此一个属性..."
- guard_sword:
- name: "&6守护之剑"
- lore:
- - ""
- - "&b&k|&b- &7&o我守护着你,到生命的最后一刻..."
- - ""
- peach_sword:
- name: "&6桃木剑"
- lore:
- - ""
- - "&b&k|&b- &7&o致敬经典僵尸片..."
- - ""
- soul_sword:
- name: "&6灵魂之剑"
- lore:
- - ""
- - "&b&k|&b- &7&o恶魔的灵魂在这里被注入..."
- - "&b&k|&b- &e&o右键 &7&o可以发出一声低吼..."
- - "&b&k|&b- &7&o将你的&e&o饱食度&7&o转化成&e&o生命值&7&o..."
- - ""
- sky_sword:
- name: "&6破天剑"
- lore:
- - ""
- - "&b&k|&b- &7&o破天,多么霸气的名字..."
- - "&b&k|&b- &e&o右键 &7&o将自己冲向天际..."
- - ""
- devil_sword:
- name: "&6斩魔剑"
- lore:
- - ""
- - "&b&k|&b- &7&o斩魔,多么威武的称号..."
- - "&b&k|&b- &e&o右键 &7&o发出圣火横扫一切黑暗..."
- - ""
- sky_devil_sword:
- name: "&6破天斩魔剑"
- lore:
- - ""
- - "&b&k|&b- &7&o破天斩魔,相继发出强大的能量..."
- - "&b&k|&b- &e&o右键 &7&o连续向前发射三次吐息并且提升自己..."
- - ""
-lores:
- per-use: "&7每次使用"
- not-appraised: "&b&k|&b- &7&o未鉴定"
- appraised: "&b&k|&b- &7&o已鉴定 &b| &d等级: &e&l{0}"
- click-to-open: "&7\u21E8 &a单击打开"
- any-random-equipment: "&f任意随机装备"
-recipes:
- compressor_mock:
- name: "&b压缩机"
- lore:
- - "&7如合成表所示"
- - "&7在压缩机中合成"
-researches:
- food: "Bump 食物"
- random_equipment: "随机装备"
- appraise: "鉴定"
- stuff: "魔法物品"
- old_stuff: "淘金"
- bow: "Bump 弓"
- peach_sword: "桃木剑"
- normal_sword: "普通的剑"
- soul_sword: "灵魂之剑"
- sky_devil: "斩天破魔"
-messages:
- no-permission: "&c你没有权限。"
- no-input: "&c请放入物品!"
- output-no-space: "&c输出空间不足!"
- not-enough-power: "&c电力不足!"
- stacked: "&c你不能使用堆叠的物品。"
- legacy: "&c你正在使用旧物品。你需要将它升级为新物品。"
- deprecated: "&c你正在使用废弃的物品,它将在不久后移除。"
- click-here: "&e单击此处:"
- food:
- cooldown: "&b&k|&b- &7&o你需要等待一段时间才能再次食用!"
- xuebi: "&b&k|&b- &7&o清凉一夏!"
- kele: "&b&k|&b- &7&o肥宅的胜利!"
- fangbianmian: "&b&k|&b- &7&o童年的味道!"
- latiao: "&b&k|&b- &7&o这辣,才够味!"
- kouxiangtang: "&b&k|&b- &7&o仙气飘飘!"
- zongzi: "&b&k|&b- &7&o是甜粽子还是咸粽子呢?"
- tool:
- getgold_spade: "&b&k|&b- &7&o哇,是金子..."
- appraisal_paper:
- legacy: "&b你的旧版品质鉴定符已更新。"
- invalid: "&c该物品无法进行鉴定!"
- success: "&a该物品现在可以进行鉴定了!"
- weapon:
- unavailable: "&b&k|&b- &7&o你现在无法发动该技能!"
- low-food-level: "&b&k|&b- &7&o你的饱食度太低!"
- cooldown: "&b&k|&b- &7&o你需要等待一段时间才能再次使用武器技能!"
- soul_sword:
- converted-part: "&b&k|&b- &7&o已将部分饱食度转化为生命值!"
- converted-all: "&b&k|&b- &7&o已将全部饱食度转化为生命值!"
- devil_sword: "&b&k|&b- &7&o斩魔,一刀致命!"
- sky_sword:
- activated: "&b&k|&b- &7&o破天,一飞冲天!"
- protected: "&b&k|&b- &7&o破天剑保护了你免受摔落伤害!"
- sky_devil_sword:
- activated: "&b&k|&b- &7&o破天斩魔,天降正义!"
- deactivated: "&b&k|&b- &7&o强化时间已经结束!"
- light_bow: "&b&k|&b- &7&o神罚!"
- wither_skull_bow: "&b&k|&b- &7&o凋零!"
- machine:
- appraisal:
- invalid: "&c该物品类型不支持鉴定!"
- not-accepted: "&c当前的鉴定类型不接受该物品。"
- appraised: "&c该物品已经鉴定过,无法进行鉴定!"
- success: "&a已鉴定!"
- attribute-grindstone:
- invalid: "&c该物品还未鉴定!"
- success: "&a已清除鉴定结果!"
-console:
- loading-appraise-types: "正在从配置文件中加载所有鉴定类型。"
- loading-appraise-type: "正在加载鉴定类型 \"{0}\"。"
- disabled-appraise-type: "鉴定类型 \"{0}\" 已被禁用,跳过加载。"
- loaded-appraise-type: "已加载鉴定类型 \"{0}\"。"
- error-loading-appraise-type: "加载鉴定类型 \"{0}\" 时发生错误: {1}"
- missing-appraise-stars: "配置文件中缺少 'appraise.stars' 部分。"
- use-default-appraise-stars: "正在使用默认鉴定星级设置。"
- invalid-appraise-stars: "你只能设置星级为 0 到 127 之间!"
- error-sound: "加载声音配置时发生错误: {0}"
- invalid-sound-config: "无法找到Bump的声音配置: {0}"
- invalid-sound-volume: "声音 \"{0}\" 的音量设置无效: {1} (必须至少为 {2})"
- invalid-sound-pitch: "声音 \"{0}\" 的音高设置无效: {1} (必须至少为 {2})"
-gui:
- appraise:
- name: "&e点击鉴定"
- lore:
- - "&7<- 在左侧放入需要鉴定的物品"
- - "&7点击这里开始鉴定"
- appraise_type_selector:
- name: "&b当前类型: &e{0}"
- lore:
- - ""
- - "&7在Bump分类中查看详情"
- - "&e点击选择该类型"
- appraise_type_selector_menu:
- title: "&6选择鉴定类型"
- lore:
- - ""
- - "&e点击选择该类型"
- appraisal_paper:
- name: "&e点击应用"
- lore:
- - "&7<- 在左侧放入物品"
- - "&7点击这里让物品可以进行鉴定"
- grind:
- name: "&e点击清除属性"
- lore:
- - "&7<- 在左侧放入已鉴定的物品"
- - "&7点击这里清除属性"
-appraise_info:
- name: "&b鉴定类型: &e{0}"
- click: "&e点击查看详情"
- equipment_type:
- name: "&a可接受的物品类型: &b{0}"
- any: "&7任意物品"
- vanilla: "&7仅原版物品"
- slimefun: "&7仅粘液科技物品"
- material:
- name: "&a是否检测物品的材料: &b{0}"
- lore_enabled:
- - "&7仅允许以下材料:"
- lore_enabled_more: "&7还有 {0} 个更多..."
- lore_disabled:
- - "&7不会检测物品的材料。"
- equipment_slot:
- name: "&a装备栏位"
- lore:
- - "&7属性将应用到"
- - "&7以下装备栏位:"
- attribute:
- name: "&e属性: &9{0}"
- range: "&7范围: &b{0} &7~ &b{1}"
- weight: "&7权重: &b{0}%"
-
diff --git a/src/main/resources/lang/zh-TW.yml b/src/main/resources/lang/zh-TW.yml
deleted file mode 100644
index ba586d29..00000000
--- a/src/main/resources/lang/zh-TW.yml
+++ /dev/null
@@ -1,302 +0,0 @@
----
-categories:
- main: "&bBump"
- armor: "&bBump - 護甲"
- food: "&bBump - 食物"
- machine: "&bBump - 機器"
- stuff: "&bBump - 魔法物品"
- tool: "&bBump - 工具"
- weapon: "&bBump - 魔法武器"
- appraise_info: "&eBump - 鑒定信息"
- wiki: "&eBump - Wiki"
-items:
- random_helmet:
- name: "&6隨機頭盔"
- lore:
- - ""
- - "&b&k|&b- &7&o我的運氣怎麼樣..."
- - "&b&k|&b- &e&o鑒定儀 &7&o隨機給予此一個屬性..."
- random_horse_armor:
- name: "&6随机馬鎧"
- lore:
- - ""
- - "&b&k|&b- &7&o我的運氣怎麼樣..."
- - "&b&k|&b- &e&o鑒定儀 &7&o隨機給予此一個屬性..."
- xuebi:
- name: "&6雪碧"
- lore:
- - ""
- - "&b&k|&b- 很甜很甜, 還冒著氣泡!"
- - ""
- kele:
- name: "&e可樂"
- lore:
- - ""
- - "&b&k|&b- 冰力十足,喝了真精神,還會飛呢!"
- - ""
- fangbianmian:
- name: "&e康師傅速食麵"
- lore:
- - ""
- - "&b&k|&b- 這個味,對辣!"
- - ""
- latiao:
- name: "&e辣條"
- lore:
- - ""
- - "&b&k|&b- 爽,吃了之後還不忘舔舔辣油..."
- - ""
- kouxiangtang:
- name: "&e口香糖"
- lore:
- - ""
- - "&b&k|&b- 很粘稠的..."
- - ""
- zongzi:
- name: "&a粽子"
- lore:
- - ""
- - "&b&k|&b- 端午節快樂!"
- - ""
- appraisal:
- name: "&b鑒定儀"
- lore:
- - ""
- - "&c&k|&7- 哦,你這是個殘次品..."
- - ""
- sun_energy:
- name: "&e光合能量"
- lore:
- - ""
- - "&b&k|&b- 變異的植物也會進行光合作用..."
- - ""
- mecha_gear:
- name: "&e機械齒輪"
- lore:
- - ""
- - "&b&k|&b- 某大型工廠淘汰下來的東西..."
- - ""
- old_coin:
- name: "&e破損的的金幣"
- lore:
- - ""
- - "&b&k|&b- 這東西能買什麼..."
- - ""
- make:
- name: "&e電腦工藝核心"
- lore:
- - ""
- - "&b&k|&b- 它用來幹什麼呢..."
- - ""
- old_cpu:
- name: "&e破損的CPU"
- lore:
- - ""
- - "&b&k|&b- 從哪家的電腦上拆下來的..."
- - ""
- cpu:
- name: "&eCPU"
- lore:
- - ""
- - "&b&k|&b- 完好無損..."
- - ""
- soul_paper:
- name: "&e靈魂之符"
- lore:
- - ""
- - "&b&k|&b- 被注入了靈魂的力量"
- - ""
- ksf_stuff:
- name: "&e速食麵調料"
- lore:
- - ""
- - "&b&k|&b- 嘶~ 是香辣味的"
- - ""
- water_sugar:
- name: "&e汽水糖"
- lore:
- - ""
- - "&b&k|&b- 雪碧? 還是可口可樂?"
- - ""
- peach_wood:
- name: "&e桃木"
- lore:
- - ""
- - "&b&k|&b- 驅邪避難"
- - ""
- update_power:
- name: "&e升級核心"
- lore:
- - ""
- - "&b&k|&b- 用來升級一些奇怪的物品..."
- - ""
- getgold_spade:
- name: "&e摸金鏟"
- lore:
- - ""
- - "&b&k|&b- 在沙子裏一定幾率挖出破損的金幣!"
- - ""
- quality_identifier:
- lore:
- - ""
- - ""
- - "&b&k|&b- 非常昂貴, 一定要保存好..."
- - ""
- appraisal_paper_armor:
- name: "&e護甲品質鑒定符"
- lore:
- - ""
- - "&b&k|&b- 給定物品隨機一個護甲屬性!"
- - "&b&k|&b- 非常昂貴,一定要保存好..."
- - ""
- appraisal_paper_damage:
- name: "&e武器品質鑒定符"
- lore:
- - ""
- - "&b&k|&b- 給定物品隨機一個攻擊屬性!"
- - "&b&k|&b- 非常昂貴,一定要保存好..."
- - ""
- appraisal_paper_horse_armor:
- name: "&e馬鎧品質鑒定符"
- lore:
- - ""
- - "&b&k|&b- 給定物品隨機一個護甲屬性!"
- - "&b&k|&b- 非常昂貴, 一定要保存好..."
- - ""
- light_bow:
- name: "&6神罰之弓"
- lore:
- - ""
- - "&b&k|&b- &7&o接受神的懲罰..."
- - ""
- witherskull_bow:
- name: "&6凋零弓"
- lore:
- - ""
- - "&b&k|&b- &7&o它發射出去的的是每一個亡靈..."
- - ""
- emer_sword:
- name: "&6綠寶石之劍"
- lore:
- - ""
- - "&b&k|&b- &7&o昂貴的綠寶石打造而成..."
- - ""
- bone_sword:
- name: "&6骨劍"
- lore:
- - ""
- - "&b&k|&b- &7&o堅硬無比..."
- - ""
- random_sword:
- name: "&6隨機短刃"
- lore:
- - ""
- - "&b&k|&b- &7&o我的運氣怎麼樣..."
- - "&b&k|&b- &e&o鑒定儀 &7&o隨機給予此一個屬性..."
- guard_sword:
- name: "&6守護之劍"
- lore:
- - ""
- - "&b&k|&b- &7&o我守護著你,到生命的最後一刻..."
- - ""
- peach_sword:
- name: "&6桃木劍"
- lore:
- - ""
- - "&b&k|&b- &7&o致敬經典僵屍片..."
- - ""
- soul_sword:
- name: "&6靈魂之劍"
- lore:
- - ""
- - "&b&k|&b- &7&o惡魔的靈魂在這裏被注入..."
- - "&b&k|&b- &e&o右鍵 &7&o可以發出一聲低吼..."
- - "&b&k|&b- &7&o將你的&e&o飽食度&7&o轉化成&e&o生命值&7&o..."
- - ""
- sky_sword:
- name: "&6破天劍"
- lore:
- - ""
- - "&b&k|&b- &7&o破天,多麼霸氣的名字..."
- - "&b&k|&b- &e&o右鍵 &7&o將自己沖向天際..."
- - ""
- devil_sword:
- name: "&6斬魔劍"
- lore:
- - ""
- - "&b&k|&b- &7&o斬魔,多麼威武的稱號..."
- - "&b&k|&b- &e&o右鍵 &7&o發出聖火橫掃一切黑暗..."
- - ""
- sky_devil_sword:
- name: "&6破天斬魔劍"
- lore:
- - ""
- - "&b&k|&b- &7&o破天斬魔,相繼發出強大的能量..."
- - ""
- - ""
-lores:
- per-use: "&7每次使用"
- not-appraised: "&b&k|&b- &7&o未鑒定"
- appraised: "&b&k|&b- &7&o已鑒定 &b| &e&l等級: {0}"
- click-to-open: "&7\u21E8 &a點擊開啟"
-researches:
- food: "Bump美食"
- random_equipment: "隨機裝備"
- appraise: "鑑定"
- stuff: "Bump魔法"
- old_stuff: "取金不易"
- bow: "Bump之弓"
- peach_sword: "桃木劍"
- normal_sword: "Bump之劍"
- soul_sword: "魂魄!"
- sky_devil: "天堂隕落地獄!"
-messages:
- no-permission: "&c你沒有權限."
- no-input: "&c請放入物品!"
- output-no-space: "&c輸出空間不足!"
- not-enough-power: "&c電力不足!"
- stacked: "&c你不能使用堆疊的物品"
- click-here: "&e點擊這裡:"
- food:
- xuebi: "&b&k|&b- &7&o清涼一夏!"
- kele: "&b&k|&b- &7&o肥宅的勝利!"
- fangbianmian: "&b&k|&b- &7&o童年的味道!"
- latiao: "&b&k|&b- &7&o這辣,才夠味!"
- kouxiangtang: "&b&k|&b- &7&o仙氣飄飄!"
- zongzi: "&b&k|&b- &7&o是甜粽子還是鹹粽子呢?"
- tool:
- getgold_spade: "&b&k|&b- &7&oOMG, 金子..."
- appraisal_paper:
- invalid: "&c該物品無法進行鑒定!"
- success: "&a該物品現在可以進行鑒定了!"
- weapon:
- unavailable: "&b&k|&b- &7&o你現在無法發動該技能!"
- low-food-level: "&b&k|&b- &7&o你的飽食度太低!"
- soul_sword:
- converted-part: "&b&k|&b- &7&o已將部分飽食度轉化為生命值!"
- converted-all: "&b&k|&b- &7&o已將全部飽食度轉化為生命值!"
- devil_sword: "&b&k|&b- &7&o斬魔, 一刀致命!"
- sky_sword:
- activated: "&b&k|&b- &7&o破天, 一飛沖天!"
- sky_devil_sword:
- activated: "&b&k|&b- &7&o破天斬魔,天降正義!"
- deactivated: "&b&k|&b- &7&o強化時間已經結束!"
- light_bow: "&b&k|&b- &7&o神罰!"
- wither_skull_bow: "&b&k|&b- &7&o凋零!"
- machine:
- appraisal:
- invalid: "&c該物品無法進行鑒定!"
- appraised: "&c該物品已經鑒定過,無法進行鑒定!"
- success: "&a已鑒定武器!"
-gui:
- appraise:
- name: "&e點擊鑒定"
- lore:
- - "&7<- 在左側放入需要鑒定的物品"
- - "&7點擊這裏開始鑒定"
- appraisal_paper:
- name: "&e點擊應用"
- lore:
- - "&7<- 在左側放入物品"
- - "&7點擊這裏讓物品可以進行鑒定"
-
diff --git a/src/main/resources/sounds.yml b/src/main/resources/sounds.yml
index e69de29b..b54f0cbc 100644
--- a/src/main/resources/sounds.yml
+++ b/src/main/resources/sounds.yml
@@ -0,0 +1,2 @@
+# This file is going to be automatically generated by the plugin
+# the sound name is the value of bukkit's Sound enum, link: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Sound.html
diff --git a/src/main/resources/tags/mob_armor.json b/src/main/resources/tags/mob_armor.json
new file mode 100644
index 00000000..002bbe73
--- /dev/null
+++ b/src/main/resources/tags/mob_armor.json
@@ -0,0 +1,8 @@
+{
+ "values": [
+ "#bump:horse_armor",
+ "#bump:carpet",
+ "minecraft:wolf_armor",
+ "minecraft:saddle"
+ ]
+}
diff --git a/src/main/resources/wiki.json b/src/main/resources/wiki.json
index 85c0590e..9c850806 100644
--- a/src/main/resources/wiki.json
+++ b/src/main/resources/wiki.json
@@ -1,39 +1,39 @@
{
- "RANDOM_HELMET": "Random-Equipment",
- "RANDOM_HORSE_ARMOR": "Random-Equipment",
- "XUEBI": "Food",
- "KELE": "Food",
- "FANGBIANMIAN": "Food",
- "LATIAO": "Food",
- "KOUXIANGTANG": "Food",
- "ZONGZI": "Food",
- "APPRAISAL": "Appraisal-Instrument",
- "ATTRIBUTE_GRINDSTONE": "Attribute-Grinder",
- "SUN_ENERGY": "Stuff",
- "MECHA_GEAR": "Stuff",
- "OLD_COIN": "Stuff",
- "MAKE": "Stuff",
- "OLD_CPU": "Stuff",
- "CPU": "Stuff",
- "SOUL_PAPER": "Stuff",
- "KSF_STUFF": "Stuff",
- "WATER_SUGAR": "Stuff",
- "PEACH_WOOD": "Stuff",
- "UPDATE_POWER": "Stuff",
- "GETGOLD_SPADE": "Getting-Gold-Shovel",
- "QUALITY_IDENTIFIER": "Quality-Identifiers",
- "APPRAISAL_PAPER_ARMOR": "Quality-Identifiers",
- "APPRAISAL_PAPER_DAMAGE": "Quality-Identifiers",
- "APPRAISAL_PAPER_HORSE_ARMOR": "Quality-Identifiers",
- "LIGHT_BOW": "Gods-Punishment-Bow",
- "WITHERSKULL_BOW": "Withered-Bow",
- "EMER_SWORD": "Weapon",
- "BONE_SWORD": "Weapon",
- "RANDOM_SWORD": "Random-Equipment",
- "GUARD_SWORD": "Weapon",
- "PEACH_SWORD": "Weapon",
- "SOUL_SWORD": "Soul-Sword",
- "SKY_SWORD": "Heaven-Breaking-Sword",
- "DEVIL_SWORD": "Demon-Slayer-Sword",
- "SKY_DEVIL_SWORD": "Heaven-demon-Crumble-Sword"
+ "RANDOM_HELMET": "Random-Equipment",
+ "RANDOM_HORSE_ARMOR": "Random-Equipment",
+ "XUEBI": "Food",
+ "KELE": "Food",
+ "FANGBIANMIAN": "Food",
+ "LATIAO": "Food",
+ "KOUXIANGTANG": "Food",
+ "ZONGZI": "Food",
+ "APPRAISAL": "Appraisal-Instrument",
+ "ATTRIBUTE_GRINDSTONE": "Attribute-Grinder",
+ "SUN_ENERGY": "Stuff",
+ "MECHA_GEAR": "Stuff",
+ "OLD_COIN": "Stuff",
+ "MAKE": "Stuff",
+ "OLD_CPU": "Stuff",
+ "CPU": "Stuff",
+ "SOUL_PAPER": "Stuff",
+ "KSF_STUFF": "Stuff",
+ "WATER_SUGAR": "Stuff",
+ "PEACH_WOOD": "Stuff",
+ "UPDATE_POWER": "Stuff",
+ "GETGOLD_SPADE": "Getting-Gold-Shovel",
+ "QUALITY_IDENTIFIER": "Quality-Identifiers",
+ "APPRAISAL_PAPER_ARMOR": "Quality-Identifiers",
+ "APPRAISAL_PAPER_DAMAGE": "Quality-Identifiers",
+ "APPRAISAL_PAPER_HORSE_ARMOR": "Quality-Identifiers",
+ "LIGHT_BOW": "Gods-Punishment-Bow",
+ "WITHERSKULL_BOW": "Withered-Bow",
+ "EMER_SWORD": "Weapon",
+ "BONE_SWORD": "Weapon",
+ "RANDOM_SWORD": "Random-Equipment",
+ "GUARD_SWORD": "Weapon",
+ "PEACH_SWORD": "Weapon",
+ "SOUL_SWORD": "Soul-Sword",
+ "SKY_SWORD": "Heaven-Breaking-Sword",
+ "DEVIL_SWORD": "Demon-Slayer-Sword",
+ "SKY_DEVIL_SWORD": "Heaven-demon-Crumble-Sword"
}