Merge pull request #175 from Crazy-Crew/switch-to-uuids

Updating storage to use uuids instead of player names
This commit is contained in:
Ryder Belserion 2024-06-16 21:42:17 -04:00 committed by GitHub
commit aecb1c4ad3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 1527 additions and 372 deletions

View File

@ -21,11 +21,11 @@ jobs:
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
java-version: 21
check-latest: true
- name: Gradle Properties Import.

View File

@ -1,2 +1,5 @@
### Changes:
- Migrated `data.yml` to use uuids instead of player names. Existing data.yml should migrate to this format.
### Fixed:
- Caught a few stragglers in the code not yet updated to the using the methods for the new item format.
- Bid now button wasn't using the value from the `config.yml`

View File

@ -2,12 +2,12 @@ plugins {
alias(libs.plugins.minotaur)
alias(libs.plugins.hangar)
`root-plugin`
`java-plugin`
}
val buildNumber: String? = System.getenv("BUILD_NUMBER")
rootProject.version = if (buildNumber != null) "1.4.2-$buildNumber" else "1.4.2"
rootProject.version = if (buildNumber != null) "1.4.3-$buildNumber" else "1.4.3"
val isSnapshot = false
@ -33,8 +33,7 @@ modrinth {
gameVersions.set(listOf(libs.versions.minecraft.get()))
loaders.add("paper")
loaders.add("purpur")
loaders.addAll("paper", "purpur")
autoAddDependsOn.set(false)
detectLoaders.set(false)

View File

@ -1,12 +1,11 @@
import com.ryderbelserion.feather.feather
plugins {
id("com.ryderbelserion.feather-logic") version "0.0.1"
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
mavenCentral()
}
dependencies {
implementation(libs.paperweight.userdev)
feather("0.0.1")
}

View File

@ -1,9 +1,23 @@
rootProject.name = "buildSrc"
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
repositories {
maven("https://repo.crazycrew.us/releases")
gradlePluginPortal()
mavenCentral()
}
}
rootProject.name = "buildSrc"
pluginManagement {
repositories {
maven("https://repo.crazycrew.us/releases")
gradlePluginPortal()
}
}
plugins {
id("com.ryderbelserion.feather-settings")
}

View File

@ -0,0 +1,46 @@
import com.ryderbelserion.feather.enums.Repository
plugins {
id("com.ryderbelserion.feather-core")
`maven-publish`
`java-library`
}
repositories {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi")
maven("https://repo.codemc.io/repository/maven-public")
maven("https://repo.oraxen.com/releases")
maven(Repository.CrazyCrewReleases.url)
maven(Repository.Jitpack.url)
flatDir { dirs("libs") }
mavenCentral()
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
tasks {
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(21)
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
processResources {
filteringCharset = Charsets.UTF_8.name()
}
}

View File

@ -1,17 +1,13 @@
import com.ryderbelserion.feather.enums.Repository
plugins {
id("root-plugin")
id("java-plugin")
}
repositories {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
maven("https://repo.triumphteam.dev/snapshots")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://maven.enginehub.org/repo")
maven("https://repo.codemc.io/repository/maven-public/")
maven("https://repo.triumphteam.dev/snapshots/")
maven("https://repo.fancyplugins.de/releases/")
flatDir { dirs("libs") }
maven(Repository.Paper.url)
}

View File

@ -1,38 +0,0 @@
plugins {
`java-library`
`maven-publish`
}
base {
archivesName.set(rootProject.name)
}
repositories {
maven("https://repo.crazycrew.us/snapshots/")
maven("https://repo.crazycrew.us/releases/")
maven("https://jitpack.io/")
mavenCentral()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of("17"))
}
tasks {
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
processResources {
filteringCharset = Charsets.UTF_8.name()
}
}

View File

@ -1,16 +1,10 @@
org.gradle.jvmargs = '-Xmx3G'
org.gradle.caching = true
org.gradle.parallel = true
org.gradle.warning.mode = all
authors = ["Ryderbelserion, Badbones69"]
website = https://modrinth.com/plugin/crazyauctions
sources = https://github.com/Crazy-Crew/CrazyAuctions
issues = https://github.com/Crazy-Crew/CrazyAuctions/issues
org.gradle.jvmargs = -Xmx3G
org.gradle.daemon = false
org.gradle.parallel = false
group = com.badbones69.crazyauctions
authors = ["Ryderbelserion, Badbones69"]
description = Auction off items in style.
apiVersion = 1.20
mcVersion = 1.20.4
isBeta = true
website = https://modrinth.com/plugin/crazyauctions
sources = https://github.com/Crazy-Crew/CrazyAuctions
issues = https://github.com/Crazy-Crew/CrazyAuctions/issues

View File

@ -1,48 +1,66 @@
[plugins]
run-paper = { id = "xyz.jpenilla.run-paper", version = "2.2.3" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
hangar = { id = "io.papermc.hangar-publish-plugin", version.ref = "hangar" }
shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" }
[versions]
kyori = "4.16.0"
bundle = "1.20.4-R0.1-SNAPSHOT"
cluster = "1.0-SNAPSHOT"
minotaur = "2.+"
# Minecraft
paper = "1.20.6-R0.1-SNAPSHOT"
minecraft = "1.20.6"
# Plugins
itemsadder = "3.6.3-beta-14"
headdatabaseapi = "1.3.1"
placeholderapi = "2.11.6"
decentholograms = "2.8.8"
fancyholograms = "2.2.0"
worldguard = "7.0.10"
oraxen = "1.171.0"
nbtapi = "2.13.0"
vault = "1.7.1"
# Libraries
triumph-cmd = "2.0.0-ALPHA-10"
tirumph-gui = "3.1.7"
jetbrains = "24.1.0"
kyori = "4.17.0"
vital = "1.5.9"
# Paper
paperweight = "1.7.1"
runPaper = "2.3.0"
hangar = "0.1.2"
paper = "1.20.4-R0.1-SNAPSHOT"
minecraft = "1.20.4"
# Other
shadowJar = "8.1.7"
# Modrinth
minotaur = "2.+"
[plugins]
paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" }
hangar = { id = "io.papermc.hangar-publish-plugin", version.ref = "hangar" }
shadowJar = { id = "io.github.goooler.shadow", version.ref = "shadowJar" }
runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
[libraries]
simple-yaml = { group = "com.github.Carleslc.Simple-YAML", name = "Simple-Yaml", version = "1.8.4" }
# Plugins
decent-holograms = { module = "com.github.decentsoftware-eu:decentholograms", version.ref = "decentholograms" }
fancy-holograms = { module = "de.oliver:FancyHolograms", version.ref = "fancyholograms" }
minimessage-api = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "kyori" }
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "kyori" }
headdatabaseapi = { module = "com.arcaniax:HeadDatabase-API", version.ref = "headdatabaseapi" }
placeholderapi = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" }
itemsadder-api = { group = "com.github.LoneDev6", name = "api-itemsadder", version = "3.6.1" }
oraxen-api = { group = "io.th0rgal", name = "oraxen", version = "1.171.0" }
placeholder-api = { group = "me.clip", name = "placeholderapi", version = "2.11.5" }
head-database-api = { group = "com.arcaniax", name = "HeadDatabase-API", version = "1.3.1" }
vault = { module = "com.github.MilkBowl:VaultAPI", version.ref = "vault" }
paperweight-userdev = { group = "io.papermc.paperweight.userdev", name = "io.papermc.paperweight.userdev.gradle.plugin", version = "1.5.11" }
publishing-modrinth = { group = "com.modrinth.minotaur", name = "Minotaur", version = "2.8.7" }
publishing-hangar = { group = "io.papermc", name = "hangar-publish-plugin", version = "0.1.2" }
itemsadder = { module = "com.github.LoneDev6:api-itemsadder", version.ref = "itemsadder" }
oraxen = { module = "io.th0rgal:oraxen", version.ref = "oraxen" }
cluster-api = { group = "com.ryderbelserion.cluster", name = "api", version.ref = "cluster" }
cluster-paper = { group = "com.ryderbelserion.cluster", name = "paper", version.ref = "cluster" }
# Libraries
triumph-cmds = { module = "dev.triumphteam:triumph-cmd-bukkit", version.ref = "triumph-cmd" }
triumph-gui = { module = "dev.triumphteam:triumph-gui", version.ref = "tirumph-gui" }
fancy-holograms = { group = "de.oliver", name = "FancyHolograms", version = "2.0.6" }
decent-holograms = { group = "com.github.decentsoftware-eu", name = "decentholograms", version = "2.8.6" }
jetbrains = { module = "org.jetbrains:annotations", version.ref = "jetbrains" }
triumph-cmds = { group = "dev.triumphteam", name = "triumph-cmd-bukkit", version = "2.0.0-ALPHA-9" }
triumph-gui = { group = "dev.triumphteam", name = "triumph-gui", version = "3.1.7" }
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version = "1.7.1" }
metrics = { group = "org.bstats", name = "bstats-bukkit", version = "3.0.2" }
config-me = { group = "ch.jalu", name = "configme", version = "1.4.1" }
vital-paper = { module = "com.ryderbelserion.vital:paper", version.ref = "vital" }
vital-core = { module = "com.ryderbelserion.vital:core", version.ref = "vital" }
[bundles]
adventure = ["minimessage-api", "adventure-api"]
holograms = ["fancy-holograms", "decent-holograms"]
triumph = ["triumph-cmds", "triumph-gui"]

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@ -1,38 +1,53 @@
plugins {
alias(libs.plugins.paperweight)
alias(libs.plugins.shadowJar)
alias(libs.plugins.runPaper)
`paper-plugin`
id("io.papermc.paperweight.userdev")
alias(libs.plugins.run.paper)
alias(libs.plugins.shadow)
}
repositories {
maven("https://repo.oraxen.com/releases/")
base {
archivesName.set(rootProject.name)
}
dependencies {
paperweight.paperDevBundle(libs.versions.bundle)
paperweight.paperDevBundle(libs.versions.paper)
implementation(libs.metrics)
compileOnly(libs.placeholderapi)
compileOnly(libs.placeholder.api)
compileOnly(libs.oraxen.api)
compileOnly(libs.oraxen)
compileOnly(libs.vault)
compileOnly(fileTree("libs").include("*.jar"))
}
tasks {
assemble {
dependsOn(reobfJar)
paperweight {
reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION
}
doLast {
copy {
from(reobfJar.get())
into(rootProject.projectDir.resolve("jars"))
val component: SoftwareComponent = components["java"]
tasks {
publishing {
repositories {
maven {
url = uri("https://repo.crazycrew.us/releases")
credentials {
this.username = System.getenv("gradle_username")
this.password = System.getenv("gradle_password")
}
}
}
publications {
create<MavenPublication>("maven") {
groupId = rootProject.group.toString()
artifactId = "${rootProject.name.lowercase()}-${project.name.lowercase()}-api"
version = rootProject.version.toString()
from(component)
}
}
}
@ -50,32 +65,36 @@ tasks {
url("https://download.luckperms.net/1544/bukkit/loader/LuckPerms-Bukkit-5.4.131.jar")
}
minecraftVersion("1.20.4")
minecraftVersion("1.20.6")
}
assemble {
dependsOn(reobfJar)
doLast {
copy {
from(reobfJar.get())
into(rootProject.projectDir.resolve("jars"))
}
}
}
shadowJar {
listOf(
"org.bstats"
).forEach {
relocate(it, "libs.$it")
}
archiveBaseName.set(rootProject.name)
archiveClassifier.set("")
}
processResources {
val properties = hashMapOf(
"name" to rootProject.name,
"version" to project.version,
"group" to rootProject.group,
"description" to rootProject.description,
"apiVersion" to providers.gradleProperty("apiVersion").get(),
"authors" to providers.gradleProperty("authors").get(),
"website" to providers.gradleProperty("website").get()
)
inputs.properties(properties)
inputs.properties("name" to rootProject.name)
inputs.properties("version" to project.version)
inputs.properties("group" to project.group)
inputs.properties("description" to project.properties["description"])
inputs.properties("apiVersion" to libs.versions.minecraft.get())
inputs.properties("authors" to project.properties["authors"])
inputs.properties("website" to project.properties["website"])
filesMatching("plugin.yml") {
expand(properties)
expand(inputs.properties)
}
}
}

View File

@ -118,7 +118,6 @@ timings:
url: https://timings.aikar.co/
verbose: false
unsupported-settings:
allow-grindstone-overstacking: false
allow-headless-pistons: false
allow-permanent-block-break-exploits: false
allow-piston-duplication: false
@ -126,6 +125,7 @@ unsupported-settings:
allow-unsafe-end-portal-teleportation: false
compression-format: ZLIB
perform-username-validation: true
skip-vanilla-damage-tick-when-shield-blocked: false
watchdog:
early-warning-delay: 10000
early-warning-every: 5000

View File

@ -12,7 +12,7 @@
# Discord: https://discord.gg/papermc
# Website: https://papermc.io/
_version: 30
_version: 31
anticheat:
anti-xray:
enabled: false
@ -131,7 +131,6 @@ entities:
wither: true
wither-skeleton: true
spiders-immune-to-poison-effect: true
undead-immune-to-certain-effects: true
sniffer:
boosted-hatch-time: default
hatch-time: default

View File

@ -5,6 +5,12 @@
"level": 4,
"bypassesPlayerLimit": false
},
{
"uuid": "42bf0b48-8574-44b5-8cce-5accf9363b05",
"name": "mitchy387",
"level": 4,
"bypassesPlayerLimit": false
},
{
"uuid": "64ccbf4e-87d2-490f-9370-8c4e53df9013",
"name": "Rukkhadevata",

View File

@ -1,61 +1,63 @@
#Minecraft server properties
#Sun Mar 24 11:23:50 EDT 2024
enable-jmx-monitoring=false
rcon.port=25575
level-seed=
gamemode=survival
enable-command-block=false
enable-query=false
generator-settings={}
enforce-secure-profile=true
level-name=world
motd=A test server
query.port=25565
pvp=true
generate-structures=true
max-chained-neighbor-updates=1000000
difficulty=peaceful
network-compression-threshold=256
max-tick-time=60000
require-resource-pack=false
use-native-transport=true
max-players=5
online-mode=true
enable-status=true
#Sun Jun 16 21:34:17 EDT 2024
accepts-transfers=false
allow-flight=false
initial-disabled-packs=
broadcast-rcon-to-ops=false
view-distance=6
server-ip=
resource-pack-prompt=
allow-nether=false
server-port=25565
enable-rcon=false
sync-chunk-writes=false
resource-pack-id=
op-permission-level=4
prevent-proxy-connections=false
hide-online-players=false
resource-pack=
entity-broadcast-range-percentage=100
simulation-distance=10
rcon.password=
player-idle-timeout=0
debug=false
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=false
spawn-npcs=true
spawn-animals=true
log-ips=false
function-permission-level=2
initial-enabled-packs=vanilla
level-type=minecraft\:normal
text-filtering-config=
spawn-monsters=true
broadcast-rcon-to-ops=false
debug=false
difficulty=peaceful
enable-command-block=false
enable-jmx-monitoring=false
enable-query=false
enable-rcon=false
enable-status=true
enforce-secure-profile=true
enforce-whitelist=false
spawn-protection=32
resource-pack-sha1=
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
gamemode=survival
generate-structures=true
generator-settings={}
hardcore=false
hide-online-players=false
initial-disabled-packs=
initial-enabled-packs=vanilla
level-name=world
level-seed=
level-type=minecraft\:normal
log-ips=false
max-chained-neighbor-updates=1000000
max-players=5
max-tick-time=60000
max-world-size=29999984
motd=A test server
network-compression-threshold=256
online-mode=true
op-permission-level=4
player-idle-timeout=0
prevent-proxy-connections=false
pvp=true
query.port=25565
rate-limit=0
rcon.password=
rcon.port=25575
region-file-compression=deflate
require-resource-pack=false
resource-pack=
resource-pack-id=
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=25565
simulation-distance=10
spawn-animals=true
spawn-monsters=true
spawn-npcs=true
spawn-protection=32
sync-chunk-writes=false
text-filtering-config=
use-native-transport=true
view-distance=6
white-list=false

View File

@ -59,6 +59,7 @@ players:
disable-saving: false
world-settings:
default:
unload-frozen-chunks: false
seed-trialchambers: 94251327
below-zero-generation-in-existing-chunks: true
hanging-tick-frequency: 100

View File

@ -4,16 +4,18 @@ import com.badbones69.crazyauctions.api.CrazyManager;
import com.badbones69.crazyauctions.api.FileManager;
import com.badbones69.crazyauctions.api.enums.Messages;
import com.badbones69.crazyauctions.api.support.PluginSupport;
import com.badbones69.crazyauctions.api.support.metrics.MetricsWrapper;
import com.badbones69.crazyauctions.api.support.MetricsWrapper;
import com.badbones69.crazyauctions.commands.AuctionCommand;
import com.badbones69.crazyauctions.commands.AuctionTab;
import com.badbones69.crazyauctions.controllers.GuiListener;
import com.badbones69.crazyauctions.controllers.MarcoListener;
import com.badbones69.crazyauctions.currency.VaultSupport;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@ -66,6 +68,16 @@ public class CrazyAuctions extends JavaPlugin {
FileManager.Files.DATA.saveFile();
}
final String uuid = configuration.getString("OutOfTime/Cancelled." + key + ".Seller");
if (uuid != null) {
OfflinePlayer player = Methods.getOfflinePlayer(uuid);
configuration.set("OutOfTime/Cancelled." + key + ".Seller", player.getUniqueId().toString());
FileManager.Files.DATA.saveFile();
}
}
}
@ -78,6 +90,26 @@ public class CrazyAuctions extends JavaPlugin {
FileManager.Files.DATA.saveFile();
}
final String uuid = configuration.getString("Items." + key + ".Seller");
if (uuid != null) {
OfflinePlayer player = Methods.getOfflinePlayer(uuid);
configuration.set("Items." + key + ".Seller", player.getUniqueId().toString());
FileManager.Files.DATA.saveFile();
}
final String bidder = configuration.getString("Items." + key + ".TopBidder");
if (bidder != null && !bidder.equals("None")) {
OfflinePlayer player = Methods.getOfflinePlayer(bidder);
configuration.set("Items." + key + ".TopBidder", player.getUniqueId().toString());
FileManager.Files.DATA.saveFile();
}
}
}
@ -103,11 +135,10 @@ public class CrazyAuctions extends JavaPlugin {
// Enable vault support if enabled.
this.support = new VaultSupport();
support.loadVault();
this.support.loadVault();
// Create bstats instance.
this.metrics = new MetricsWrapper();
this.metrics.start();
this.metrics = new MetricsWrapper(this, 4624);
}
private void registerCommand(PluginCommand pluginCommand, TabCompleter tabCompleter, CommandExecutor commandExecutor) {

View File

@ -71,10 +71,10 @@ public class Methods {
return true;
}
public static Player getPlayer(String name) {
try {
return Bukkit.getServer().getPlayer(name);
return Bukkit.getServer().getPlayer(UUID.fromString(name));
} catch (Exception e) {
return null;
}
@ -89,7 +89,7 @@ public class Methods {
}
public static OfflinePlayer getOfflinePlayer(String name) {
return Bukkit.getServer().getOfflinePlayer(name);
return Bukkit.getServer().getOfflinePlayer(UUID.fromString(name));
}
public static boolean isOnline(String name) {

View File

@ -37,7 +37,7 @@ public class CrazyManager {
if (data.contains("Items")) {
for (String i : data.getConfigurationSection("Items").getKeys(false)) {
if (data.getString("Items." + i + ".Seller").equalsIgnoreCase(player.getName())) {
if (data.getString("Items." + i + ".Seller").equalsIgnoreCase(player.getUniqueId().toString())) {
if (data.getBoolean("Items." + i + ".Biddable")) {
if (type == ShopType.BID) {
items.add(Methods.fromBase64(data.getString("Items." + i + ".Item")));

View File

@ -0,0 +1,955 @@
package com.badbones69.crazyauctions.api;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
public class CustomMetrics {
private final JavaPlugin plugin;
private final MetricsBase metricsBase;
/**
* Creates a new Metrics instance.
*
* @param serviceId The id of the service. It can be found at <a href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public CustomMetrics(JavaPlugin plugin, int serviceId) {
this.plugin = plugin;
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
if (!config.isSet("serverUuid")) {
config.addDefault("enabled", true);
config.addDefault("serverUuid", UUID.randomUUID().toString());
config.addDefault("logFailedRequests", false);
config.addDefault("logSentData", false);
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config
.options()
.setHeader(
List.of(
"bStats (https://bStats.org) collects some basic information for plugin authors, like how",
"many people use their plugin and their total player count. It's recommended to keep bStats",
"enabled, but if you're not comfortable with this, you can turn this setting off. There is no",
"performance penalty associated with having metrics enabled, and data sent to bStats is fully",
"anonymous."
))
.copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) {}
}
// Load the data
boolean enabled = config.getBoolean("enabled", true);
String serverUUID = config.getString("serverUuid");
boolean logErrors = config.getBoolean("logFailedRequests", false);
boolean logSentData = config.getBoolean("logSentData", false);
boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false);
this.metricsBase = new MetricsBase(
"bukkit",
serverUUID,
serviceId,
enabled,
this::appendPlatformData,
this::appendServiceData,
submitDataTask -> plugin.getServer().getGlobalRegionScheduler().execute(plugin, submitDataTask),
plugin::isEnabled,
(message, error) -> plugin.getLogger().log(Level.WARNING, message, error),
(message) -> plugin.getLogger().log(Level.INFO, message),
logErrors,
logSentData,
logResponseStatusText);
}
/**
* Shuts down the underlying scheduler service.
*/
public void shutdown() {
this.metricsBase.shutdown();
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
this.metricsBase.addCustomChart(chart);
}
private void appendPlatformData(JsonObjectBuilder builder) {
builder.appendField("playerAmount", getPlayerAmount());
builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0);
builder.appendField("bukkitVersion", Bukkit.getVersion());
builder.appendField("bukkitName", Bukkit.getName());
builder.appendField("javaVersion", System.getProperty("java.version"));
builder.appendField("osName", System.getProperty("os.name"));
builder.appendField("osArch", System.getProperty("os.arch"));
builder.appendField("osVersion", System.getProperty("os.version"));
builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
}
private void appendServiceData(JsonObjectBuilder builder) {
builder.appendField("pluginVersion", this.plugin.getPluginMeta().getVersion());
}
private int getPlayerAmount() {
try {
// Around MC 1.8 the return type was changed from an array to a collection,
// This fixes java.lang.NoSuchMethodError:
// org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
return onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
// Just use the new method if the reflection failed
return Bukkit.getOnlinePlayers().size();
}
}
public static class MetricsBase {
/**
* The version of the Metrics class.
*/
public static final String METRICS_VERSION = "3.0.2";
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private final ScheduledExecutorService scheduler;
private final String platform;
private final String serverUuid;
private final int serviceId;
private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
private final Consumer<Runnable> submitTaskConsumer;
private final Supplier<Boolean> checkServiceEnabledSupplier;
private final BiConsumer<String, Throwable> errorLogger;
private final Consumer<String> infoLogger;
private final boolean logErrors;
private final boolean logSentData;
private final boolean logResponseStatusText;
private final Set<CustomChart> customCharts = new HashSet<>();
private final boolean enabled;
/**
* Creates a new MetricsBase class instance.
*
* @param platform The platform of the service.
* @param serviceId The id of the service.
* @param serverUuid The server uuid.
* @param enabled Whether data sending is enabled.
* @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all platform-specific data.
* @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all service-specific data.
* @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
* used to delegate the data collection to a another thread to prevent errors caused by
* concurrency. Can be {@code null}.
* @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
* @param errorLogger A consumer that accepts log message and an error.
* @param infoLogger A consumer that accepts info log messages.
* @param logErrors Whether errors should be logged.
* @param logSentData Whether the scent data should be logged.
* @param logResponseStatusText Whether the response status text should be logged.
*/
public MetricsBase(
String platform,
String serverUuid,
int serviceId,
boolean enabled,
Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
Consumer<JsonObjectBuilder> appendServiceDataConsumer,
Consumer<Runnable> submitTaskConsumer,
Supplier<Boolean> checkServiceEnabledSupplier,
BiConsumer<String, Throwable> errorLogger,
Consumer<String> infoLogger,
boolean logErrors,
boolean logSentData,
boolean logResponseStatusText) {
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1, task -> new Thread(task, "bStats-Metrics"));
// We want delayed tasks (non-periodic) that will execute in the future to be
// cancelled when the scheduler is shutdown.
// Otherwise, we risk preventing the server from shutting down even when
// MetricsBase#shutdown() is called
scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
this.scheduler = scheduler;
this.platform = platform;
this.serverUuid = serverUuid;
this.serviceId = serviceId;
this.enabled = enabled;
this.appendPlatformDataConsumer = appendPlatformDataConsumer;
this.appendServiceDataConsumer = appendServiceDataConsumer;
this.submitTaskConsumer = submitTaskConsumer;
this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
this.errorLogger = errorLogger;
this.infoLogger = infoLogger;
this.logErrors = logErrors;
this.logSentData = logSentData;
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
// WARNING: Removing the option to opt-out will get your plugin banned from
// bStats
startSubmitting();
}
}
/**
* Gzips the given string.
*
* @param str The string to gzip.
* @return The gzipped string.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
public void addCustomChart(CustomChart chart) {
this.customCharts.add(chart);
}
public void shutdown() {
this.scheduler.shutdown();
}
private void startSubmitting() {
final Runnable submitTask =
() -> {
if (!this.enabled || !this.checkServiceEnabledSupplier.get()) {
// Submitting data or service is disabled
this.scheduler.shutdown();
return;
}
if (this.submitTaskConsumer != null) {
this.submitTaskConsumer.accept(this::submitData);
} else {
this.submitData();
}
};
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven
// distribution of requests on the
// bStats backend. To circumvent this problem, we introduce some randomness into
// the initial and second delay.
// WARNING: You must not modify and part of this Metrics class, including the
// submit delay or frequency!
// WARNING: Modifying this code will get your plugin banned on bStats. Just
// don't do it!
long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
this.scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
this.scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
}
private void submitData() {
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
this.appendPlatformDataConsumer.accept(baseJsonBuilder);
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
this.appendServiceDataConsumer.accept(serviceJsonBuilder);
JsonObjectBuilder.JsonObject[] chartData =
this.customCharts.stream()
.map(customChart -> customChart.getRequestJsonObject(this.errorLogger, this.logErrors))
.filter(Objects::nonNull)
.toArray(JsonObjectBuilder.JsonObject[]::new);
serviceJsonBuilder.appendField("id", this.serviceId);
serviceJsonBuilder.appendField("customCharts", chartData);
baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
baseJsonBuilder.appendField("serverUUID", this.serverUuid);
baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
this.scheduler.execute(
() -> {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (this.logErrors) {
this.errorLogger.accept("Could not submit bStats metrics data", e);
}
}
});
}
private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
if (this.logSentData) {
this.infoLogger.accept("Sent bStats metrics data: " + data.toString());
}
String url = String.format(REPORT_URL, this.platform);
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "Metrics-Service/1");
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
if (this.logResponseStatusText) {
this.infoLogger.accept("Sent data to bStats and received response: " + builder);
}
}
/**
* Checks that the class was properly relocated.
*/
private void checkRelocation() {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D
final String defaultPackage = new String(new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure no one just copy & pastes the example and uses the wrong package names
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
String value = this.callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = this.callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = this.callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = this.callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[]{entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = this.callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = this.callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
protected CustomChart(String chartId) {
if (chartId == null) {
throw new IllegalArgumentException("chartId must not be null");
}
this.chartId = chartId;
}
public JsonObjectBuilder.JsonObject getRequestJsonObject(BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
JsonObjectBuilder builder = new JsonObjectBuilder();
builder.appendField("chartId", this.chartId);
try {
JsonObjectBuilder.JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
builder.appendField("data", data);
} catch (Throwable t) {
if (logErrors) {
errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return builder.build();
}
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = this.callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
/**
* An extremely simple JSON builder.
*
* <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
* for its use-case.
*/
public static class JsonObjectBuilder {
private StringBuilder builder = new StringBuilder();
private boolean hasAtLeastOneField = false;
public JsonObjectBuilder() {
this.builder.append("{");
}
/**
* Escapes the given string like stated in <a href="https://www.ietf.org/rfc/rfc4627.txt">...</a>.
*
* <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
* Compact escapes are not used (e.g., '\n' is escaped as "" and not as "\n").
*
* @param value The value to escape.
* @return The escaped value.
*/
private static String escape(String value) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '"') {
builder.append("\\\"");
} else if (c == '\\') {
builder.append("\\\\");
} else if (c <= '\u000F') {
builder.append("\\u000").append(Integer.toHexString(c));
} else if (c <= '\u001F') {
builder.append("\\u00").append(Integer.toHexString(c));
} else {
builder.append(c);
}
}
return builder.toString();
}
/**
* Appends a null field to the JSON.
*
* @param key The key of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendNull(String key) {
appendFieldUnescaped(key, "null");
return this;
}
/**
* Appends a string field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String value) {
if (value == null) {
throw new IllegalArgumentException("JSON value must not be null");
}
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
return this;
}
/**
* Appends an integer field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int value) {
appendFieldUnescaped(key, String.valueOf(value));
return this;
}
/**
* Appends an object to the JSON.
*
* @param key The key of the field.
* @param object The object.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject object) {
if (object == null) {
throw new IllegalArgumentException("JSON object must not be null");
}
appendFieldUnescaped(key, object.toString());
return this;
}
/**
* Appends a string array to the JSON.
*
* @param key The key of the field.
* @param values The string array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).map(value -> "\"" + escape(value) + "\"").collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an integer array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an object array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends a field to the object.
*
* @param key The key of the field.
* @param escapedValue The escaped value of the field.
*/
private void appendFieldUnescaped(String key, String escapedValue) {
if (this.builder == null) {
throw new IllegalStateException("JSON has already been built");
}
if (key == null) {
throw new IllegalArgumentException("JSON key must not be null");
}
if (this.hasAtLeastOneField) {
this.builder.append(",");
}
this.builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
this.hasAtLeastOneField = true;
}
/**
* Builds the JSON string and invalidates this builder.
*
* @return The built JSON string.
*/
public JsonObject build() {
if (this.builder == null) {
throw new IllegalStateException("JSON has already been built");
}
JsonObject object = new JsonObject(this.builder.append("}").toString());
this.builder = null;
return object;
}
/**
* A super simple representation of a JSON object.
*
* <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
* allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
* JsonObject)}.
*/
public static class JsonObject {
private final String value;
private JsonObject(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}
}
}

View File

@ -4,15 +4,12 @@ import com.badbones69.crazyauctions.CrazyAuctions;
import com.badbones69.crazyauctions.Methods;
import com.badbones69.crazyauctions.api.support.PluginSupport;
import com.badbones69.crazyauctions.api.support.SkullCreator;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.th0rgal.oraxen.api.OraxenItems;
import me.clip.placeholderapi.PlaceholderAPI;
import net.minecraft.nbt.TagParser;
import org.bukkit.*;
import org.bukkit.block.Banner;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@ -36,7 +33,6 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -316,19 +312,6 @@ public class ItemBuilder {
}
if (this.itemStack.getType() != Material.AIR) {
// If item data is not empty. We ignore all other options and simply return.
if (!this.itemData.isEmpty()) {
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(getItemStack());
try {
nmsItem.setTag(TagParser.parseTag(this.itemData));
} catch (CommandSyntaxException exception) {
this.plugin.getLogger().log(Level.WARNING, "Failed to set nms tag.", exception);
}
return CraftItemStack.asBukkitCopy(nmsItem);
}
getItemStack().setAmount(this.itemAmount);
getItemStack().editMeta(itemMeta -> {
@ -412,17 +395,14 @@ public class ItemBuilder {
itemMeta.setUnbreakable(this.isUnbreakable);
if (this.isGlowing) {
if (!itemMeta.hasEnchants()) {
itemMeta.addEnchant(Enchantment.LUCK, 1, false);
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
itemMeta.setEnchantmentGlintOverride(true);
}
itemMeta.setDisplayName(getUpdatedName());
itemMeta.setLore(getUpdatedLore());
});
} else {
Logger logger = this.plugin.getLogger();
Logger logger = plugin.getLogger();
logger.warning("Material cannot be of type AIR or null, If you see this.");
logger.warning("in your console but do not have any invalid items. You can");
@ -1239,27 +1219,27 @@ public class ItemBuilder {
if (type != null) {
if (type.equals(PotionEffectType.FIRE_RESISTANCE)) {
return PotionType.FIRE_RESISTANCE;
} else if (type.equals(PotionEffectType.HARM)) {
return PotionType.INSTANT_DAMAGE;
} else if (type.equals(PotionEffectType.HEAL)) {
return PotionType.INSTANT_HEAL;
} else if (type.equals(PotionEffectType.INSTANT_DAMAGE)) {
return PotionType.STRONG_HARMING;
} else if (type.equals(PotionEffectType.INSTANT_HEALTH)) {
return PotionType.HEALING;
} else if (type.equals(PotionEffectType.INVISIBILITY)) {
return PotionType.INVISIBILITY;
} else if (type.equals(PotionEffectType.JUMP)) {
return PotionType.JUMP;
} else if (type.equals(PotionEffectType.getByName("LUCK"))) {
return PotionType.valueOf("LUCK");
} else if (type.equals(PotionEffectType.JUMP_BOOST)) {
return PotionType.LEAPING;
} else if (type.equals(PotionEffectType.LUCK)) {
return PotionType.LUCK;
} else if (type.equals(PotionEffectType.NIGHT_VISION)) {
return PotionType.NIGHT_VISION;
} else if (type.equals(PotionEffectType.POISON)) {
return PotionType.POISON;
} else if (type.equals(PotionEffectType.REGENERATION)) {
return PotionType.REGEN;
} else if (type.equals(PotionEffectType.SLOW)) {
return PotionType.REGENERATION;
} else if (type.equals(PotionEffectType.SLOWNESS)) {
return PotionType.SLOWNESS;
} else if (type.equals(PotionEffectType.SPEED)) {
return PotionType.SPEED;
} else if (type.equals(PotionEffectType.INCREASE_DAMAGE)) {
return PotionType.SWIFTNESS;
} else if (type.equals(PotionEffectType.STRENGTH)) {
return PotionType.STRENGTH;
} else if (type.equals(PotionEffectType.WATER_BREATHING)) {
return PotionType.WATER_BREATHING;
@ -1420,6 +1400,7 @@ public class ItemBuilder {
private static Map<String, Color> createMap() {
Map<String, Color> map = new HashMap<>();
map.put("AQUA", Color.AQUA);
map.put("BLACK", Color.BLACK);
map.put("BLUE", Color.BLUE);
@ -1437,12 +1418,14 @@ public class ItemBuilder {
map.put("TEAL", Color.TEAL);
map.put("WHITE", Color.WHITE);
map.put("YELLOW", Color.YELLOW);
return map;
}
public static Color getColor(String color) {
if (color != null && !color.isBlank()) {
Color mappedColor = (Color)colors.get(color.toUpperCase());
Color mappedColor = colors.get(color.toUpperCase());
if (mappedColor != null) {
return mappedColor;
} else {

View File

@ -20,7 +20,7 @@ public enum Category {
/**
* @param name Name of the Shop Type.
*/
private Category(String name, ArrayList<Material> items) {
Category(String name, ArrayList<Material> items) {
this.name = name;
this.items = items;
}

View File

@ -6,6 +6,7 @@ import org.bukkit.configuration.file.FileConfiguration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public enum Messages {
@ -57,12 +58,12 @@ public enum Messages {
private String defaultMessage;
private List<String> defaultListMessage;
private Messages(String path, String defaultMessage) {
Messages(String path, String defaultMessage) {
this.path = path;
this.defaultMessage = defaultMessage;
}
private Messages(String path, List<String> defaultListMessage) {
Messages(String path, List<String> defaultListMessage) {
this.path = path;
this.defaultListMessage = defaultListMessage;
}
@ -75,14 +76,13 @@ public enum Messages {
return message;
}
public static String convertList(List<String> list, HashMap<String, String> placeholders) {
String message = "";
for (String m : list) {
message += Methods.color(m) + "\n";
}
public static String convertList(List<String> list, Map<String, String> placeholders) {
String message = convertList(list);
for (String ph : placeholders.keySet()) {
message = Methods.color(message.replace(ph, placeholders.get(ph))).replace(ph, placeholders.get(ph).toLowerCase());
}
return message;
}
@ -99,6 +99,7 @@ public enum Messages {
}
}
}
if (saveFile) {
Files.MESSAGES.saveFile();
}
@ -120,8 +121,9 @@ public enum Messages {
}
}
public String getMessage(HashMap<String, String> placeholders) {
public String getMessage(Map<String, String> placeholders) {
String message;
if (isList()) {
if (exists()) {
message = Methods.color(convertList(Files.MESSAGES.getFile().getStringList("Messages." + path), placeholders));
@ -134,12 +136,14 @@ public enum Messages {
} else {
message = Methods.getPrefix(getDefaultMessage());
}
for (String ph : placeholders.keySet()) {
if (message.contains(ph)) {
message = message.replace(ph, placeholders.get(ph)).replace(ph, placeholders.get(ph).toLowerCase());
}
}
}
return message;
}
@ -161,6 +165,7 @@ public enum Messages {
public String getMessageNoPrefix(HashMap<String, String> placeholders) {
String message;
if (isList()) {
if (exists()) {
message = Methods.color(convertList(Files.MESSAGES.getFile().getStringList("Messages." + path), placeholders));
@ -173,12 +178,14 @@ public enum Messages {
} else {
message = Methods.color(getDefaultMessage());
}
for (String ph : placeholders.keySet()) {
if (message.contains(ph)) {
message = message.replace(ph, placeholders.get(ph)).replace(ph, placeholders.get(ph).toLowerCase());
}
}
}
return message;
}
@ -205,5 +212,4 @@ public enum Messages {
private List<String> getDefaultListMessage() {
return defaultListMessage;
}
}

View File

@ -1,6 +1,6 @@
package com.badbones69.crazyauctions.api.enums;
public enum Reaons {
public enum Reasons {
/**
* Cancelled by an administrator.

View File

@ -33,5 +33,4 @@ public enum ShopType {
public String getName() {
return name;
}
}

View File

@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -36,7 +37,7 @@ public class AuctionBuyEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -51,5 +52,4 @@ public class AuctionBuyEvent extends Event {
public long getPrice() {
return price;
}
}

View File

@ -1,11 +1,12 @@
package com.badbones69.crazyauctions.api.events;
import com.badbones69.crazyauctions.api.enums.Reaons;
import com.badbones69.crazyauctions.api.enums.Reasons;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -20,7 +21,7 @@ public class AuctionCancelledEvent extends Event {
private final boolean isOnline;
private final ItemStack item;
private final Reaons reason;
private final Reasons reason;
private OfflinePlayer offlinePlayer;
private Player onlinePlayer;
@ -30,7 +31,7 @@ public class AuctionCancelledEvent extends Event {
* @param offlinePlayer The player whose item is cancelled.
* @param item The item that is cancelled.
*/
public AuctionCancelledEvent(OfflinePlayer offlinePlayer, ItemStack item, Reaons reason) {
public AuctionCancelledEvent(OfflinePlayer offlinePlayer, ItemStack item, Reasons reason) {
this.offlinePlayer = offlinePlayer;
this.item = item;
this.isOnline = false;
@ -42,7 +43,7 @@ public class AuctionCancelledEvent extends Event {
* @param onlinePlayer The player whose item is cancelled.
* @param item The item that is cancelled.
*/
public AuctionCancelledEvent(Player onlinePlayer, ItemStack item, Reaons reason) {
public AuctionCancelledEvent(Player onlinePlayer, ItemStack item, Reasons reason) {
this.onlinePlayer = onlinePlayer;
this.item = item;
this.isOnline = true;
@ -53,7 +54,7 @@ public class AuctionCancelledEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -73,8 +74,7 @@ public class AuctionCancelledEvent extends Event {
return item;
}
public Reaons getReason() {
public Reasons getReason() {
return reason;
}
}

View File

@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -49,7 +50,7 @@ public class AuctionExpireEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -68,5 +69,4 @@ public class AuctionExpireEvent extends Event {
public ItemStack getItem() {
return item;
}
}

View File

@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -39,7 +40,7 @@ public class AuctionListEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -58,5 +59,4 @@ public class AuctionListEvent extends Event {
public long getPrice() {
return price;
}
}

View File

@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -32,7 +33,7 @@ public class AuctionNewBidEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -47,5 +48,4 @@ public class AuctionNewBidEvent extends Event {
public long getBid() {
return bid;
}
}

View File

@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
*
@ -35,7 +36,7 @@ public class AuctionWinBidEvent extends Event {
return handlers;
}
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}
@ -50,5 +51,4 @@ public class AuctionWinBidEvent extends Event {
public long getBid() {
return bid;
}
}

View File

@ -0,0 +1,16 @@
package com.badbones69.crazyauctions.api.support;
import com.badbones69.crazyauctions.CrazyAuctions;
import com.badbones69.crazyauctions.api.CustomMetrics;
public class MetricsWrapper extends CustomMetrics {
/**
* Creates a new Metrics instance.
*
* @param serviceId The id of the service. It can be found at <a href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public MetricsWrapper(CrazyAuctions plugin, int serviceId) {
super(plugin, serviceId);
}
}

View File

@ -1,36 +0,0 @@
package com.badbones69.crazyauctions.api.support.metrics;
import com.badbones69.crazyauctions.CrazyAuctions;
import org.bstats.bukkit.Metrics;
import org.jetbrains.annotations.NotNull;
public class MetricsWrapper {
@NotNull
private final CrazyAuctions plugin = CrazyAuctions.get();
private Metrics metrics;
public void start() {
if (this.metrics != null) {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("Metrics is already enabled.");
return;
}
this.metrics = new Metrics(this.plugin, 4624);
if (this.plugin.isLogging()) this.plugin.getLogger().fine("Metrics has been enabled.");
}
public void stop() {
if (this.metrics == null) {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("Metrics isn't enabled so we do nothing.");
return;
}
this.metrics.shutdown();
this.metrics = null;
if (this.plugin.isLogging()) this.plugin.getLogger().fine("Metrics has been turned off.");
}
}

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.Random;
import java.util.UUID;
import java.util.logging.Level;
public class AuctionCommand implements CommandExecutor {
@ -100,7 +101,7 @@ public class AuctionCommand implements CommandExecutor {
if (item != null && item.getType() != Material.AIR) {
// For testing as another player
String seller = "Test-Account";
String seller = UUID.randomUUID().toString();
for (int it = 1; it <= times; it++) {
int num = 1;
@ -113,12 +114,12 @@ public class AuctionCommand implements CommandExecutor {
data.set("Items." + num + ".Seller", seller);
if (args[0].equalsIgnoreCase("bid")) {
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Bid-Time")));
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Bid-Time", "2m 30s")));
} else {
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Sell-Time")));
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Sell-Time", "2d")));
}
data.set("Items." + num + ".Full-Time", Methods.convertToMill(config.getString("Settings.Full-Expire-Time")));
data.set("Items." + num + ".Full-Time", Methods.convertToMill(config.getString("Settings.Full-Expire-Time", "10d")));
int id = random.nextInt(Integer.MAX_VALUE);
for (String i : data.getConfigurationSection("Items").getKeys(false))
@ -271,21 +272,21 @@ public class AuctionCommand implements CommandExecutor {
long price = Long.parseLong(args[1]);
if (args[0].equalsIgnoreCase("bid")) {
if (price < config.getLong("Settings.Minimum-Bid-Price")) {
if (price < config.getLong("Settings.Minimum-Bid-Price", 100)) {
player.sendMessage(Messages.BID_PRICE_TO_LOW.getMessage());
return true;
}
if (price > config.getLong("Settings.Max-Beginning-Bid-Price")) {
if (price > config.getLong("Settings.Max-Beginning-Bid-Price", 1000000)) {
player.sendMessage(Messages.BID_PRICE_TO_HIGH.getMessage());
return true;
}
} else {
if (price < config.getLong("Settings.Minimum-Sell-Price")) {
if (price < config.getLong("Settings.Minimum-Sell-Price", 10)) {
player.sendMessage(Messages.SELL_PRICE_TO_LOW.getMessage());
return true;
}
if (price > config.getLong("Settings.Max-Beginning-Sell-Price")) {
if (price > config.getLong("Settings.Max-Beginning-Sell-Price", 1000000)) {
player.sendMessage(Messages.SELL_PRICE_TO_HIGH.getMessage());
return true;
}
@ -352,7 +353,7 @@ public class AuctionCommand implements CommandExecutor {
return true;
}
if (!config.getBoolean("Settings.Allow-Damaged-Items")) {
if (!config.getBoolean("Settings.Allow-Damaged-Items", false)) {
for (Material i : getDamageableItems()) {
if (item.getType() == i) {
if (item.getDurability() > 0) {
@ -368,7 +369,7 @@ public class AuctionCommand implements CommandExecutor {
return true;
}
String seller = player.getName();
String seller = player.getUniqueId().toString();
int num = 1;
Random random = new Random();
@ -378,12 +379,12 @@ public class AuctionCommand implements CommandExecutor {
data.set("Items." + num + ".Seller", seller);
if (args[0].equalsIgnoreCase("bid")) {
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Bid-Time")));
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Bid-Time", "2m 30s")));
} else {
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Sell-Time")));
data.set("Items." + num + ".Time-Till-Expire", Methods.convertToMill(config.getString("Settings.Sell-Time", "2d")));
}
data.set("Items." + num + ".Full-Time", Methods.convertToMill(config.getString("Settings.Full-Expire-Time")));
data.set("Items." + num + ".Full-Time", Methods.convertToMill(config.getString("Settings.Full-Expire-Time", "10d")));
int id = random.nextInt(999999);
// Runs 3x to check for same ID.
for (String i : data.getConfigurationSection("Items").getKeys(false))

View File

@ -6,14 +6,15 @@ import com.badbones69.crazyauctions.api.*;
import com.badbones69.crazyauctions.api.FileManager.Files;
import com.badbones69.crazyauctions.api.builders.ItemBuilder;
import com.badbones69.crazyauctions.api.enums.Category;
import com.badbones69.crazyauctions.api.enums.Reaons;
import com.badbones69.crazyauctions.api.enums.Messages;
import com.badbones69.crazyauctions.api.enums.Reasons;
import com.badbones69.crazyauctions.api.enums.ShopType;
import com.badbones69.crazyauctions.api.events.AuctionBuyEvent;
import com.badbones69.crazyauctions.api.events.AuctionCancelledEvent;
import com.badbones69.crazyauctions.api.events.AuctionNewBidEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.configuration.file.FileConfiguration;
@ -27,10 +28,10 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
public class GuiListener implements Listener {
@ -73,9 +74,32 @@ public class GuiListener implements Listener {
if (data.getBoolean("Items." + i + ".Biddable")) {
if (sell == ShopType.BID) {
String seller = data.getString("Items." + i + ".Seller");
OfflinePlayer target = null;
if (seller != null) {
target = Methods.getOfflinePlayer(seller);
}
String price = Methods.getPrice(i, false);
String time = Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"));
OfflinePlayer bidder = null;
String topbidder = data.getString("Items." + i + ".TopBidder");
for (String l : config.getStringList("Settings.GUISettings.Bidding")) {
lore.add(l.replace("%TopBid%", Methods.getPrice(i, false)).replace("%topbid%", Methods.getPrice(i, false)).replace("%Seller%", seller).replace("%seller%", seller).replace("%TopBidder%", topbidder).replace("%topbidder%", topbidder).replace("%Time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))));
if (topbidder != null && !topbidder.equals("None")) {
bidder = Methods.getOfflinePlayer(topbidder);
}
for (String key : config.getStringList("Settings.GUISettings.Bidding")) {
String line = key.replace("%TopBid%", price).replace("%topbid%", price);
line = target != null ? line.replace("%Seller%", target.getName()).replace("%seller%", target.getName()) : line.replace("%Seller%", "N/A").replace("%seller%", "N/A");
line = bidder != null ? line.replace("%TopBidder%", bidder.getName()).replace("%topbidder%", bidder.getName()) : line.replace("%TopBidder%", "N/A").replace("%topbidder%", "N/A");
lore.add(line.replace("%Time%", time).replace("%time%", time));
}
itemBuilder.setLore(lore);
@ -86,8 +110,23 @@ public class GuiListener implements Listener {
}
} else {
if (sell == ShopType.SELL) {
String seller = data.getString("Items." + i + ".Seller");
OfflinePlayer target = null;
if (seller != null) {
target = Methods.getOfflinePlayer(seller);
}
String price = Methods.getPrice(i, false);
String time = Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"));
String format = String.format(Locale.ENGLISH, "%,d", Long.parseLong(price));
for (String l : config.getStringList("Settings.GUISettings.SellingItemLore")) {
lore.add(l.replace("%Price%", String.format(Locale.ENGLISH, "%,d", Long.parseLong(Methods.getPrice(i, false)))).replace("%price%", String.format(Locale.ENGLISH, "%,d", Long.parseLong(Methods.getPrice(i, false)))).replace("%Seller%", data.getString("Items." + i + ".Seller")).replace("%seller%", data.getString("Items." + i + ".Seller")).replace("%Time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))));
lore.add(l.replace("%Price%", format).replace("%price%", format)
.replace("%Seller%", target != null ? target.getName() : "N/A").replace("%seller%", target != null ? target.getName() : "N/A")
.replace("%Time%", time).replace("%time%", time));
}
itemBuilder.setLore(lore);
@ -248,10 +287,17 @@ public class GuiListener implements Listener {
if (data.contains("Items")) {
for (String i : data.getConfigurationSection("Items").getKeys(false)) {
if (data.getString("Items." + i + ".Seller").equalsIgnoreCase(player.getName())) {
if (data.getString("Items." + i + ".Seller").equalsIgnoreCase(player.getUniqueId().toString())) {
List<String> lore = new ArrayList<>();
String price = Methods.getPrice(i, false);
String time = Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"));
for (String l : config.getStringList("Settings.GUISettings.CurrentLore")) {
lore.add(l.replace("%Price%", Methods.getPrice(i, false)).replace("%price%", Methods.getPrice(i, false)).replace("%Time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))));
lore.add(l.replace("%Price%", price)
.replace("%price%", price)
.replace("%Time%", time)
.replace("%time%", time));
}
ItemBuilder itemBuilder = ItemBuilder.convertItemStack(data.getString("Items." + i + ".Item"));
@ -285,10 +331,17 @@ public class GuiListener implements Listener {
if (data.contains("OutOfTime/Cancelled")) {
for (String i : data.getConfigurationSection("OutOfTime/Cancelled").getKeys(false)) {
if (data.getString("OutOfTime/Cancelled." + i + ".Seller") != null) {
if (data.getString("OutOfTime/Cancelled." + i + ".Seller").equalsIgnoreCase(player.getName())) {
if (data.getString("OutOfTime/Cancelled." + i + ".Seller").equalsIgnoreCase(player.getUniqueId().toString())) {
List<String> lore = new ArrayList<>();
String price = Methods.getPrice(i, true);
String time = Methods.convertToTime(data.getLong("OutOfTime/Cancelled." + i + ".Full-Time"));
for (String l : config.getStringList("Settings.GUISettings.Cancelled/ExpiredLore")) {
lore.add(l.replace("%Price%", Methods.getPrice(i, true)).replace("%price%", Methods.getPrice(i, true)).replace("%Time%", Methods.convertToTime(data.getLong("OutOfTime/Cancelled." + i + ".Full-Time"))).replace("%time%", Methods.convertToTime(data.getLong("OutOfTime/Cancelled." + i + ".Full-Time"))));
lore.add(l.replace("%Price%", price)
.replace("%price%", price)
.replace("%Time%", time)
.replace("%time%", time));
}
ItemBuilder itemBuilder = ItemBuilder.convertItemStack(data.getString("OutOfTime/Cancelled." + i + ".Item"));
@ -392,8 +445,24 @@ public class GuiListener implements Listener {
}
List<String> lore = new ArrayList<>();
String price = Methods.getPrice(ID, false);
String time = Methods.convertToTime(data.getLong("Items." + ID + ".Time-Till-Expire"));
OfflinePlayer target = null;
String id = data.getString("Items." + ID + ".Seller");
if (id != null) {
target = Methods.getOfflinePlayer(id);
}
for (String l : config.getStringList("Settings.GUISettings.SellingItemLore")) {
lore.add(l.replace("%Price%", Methods.getPrice(ID, false)).replace("%price%", Methods.getPrice(ID, false)).replace("%Seller%", data.getString("Items." + ID + ".Seller")).replace("%seller%", data.getString("Items." + ID + ".Seller")).replace("%Time%", Methods.convertToTime(data.getLong("Items." + l + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + l + ".Time-Till-Expire"))));
lore.add(l.replace("%Price%", price).replace("%price%", price)
.replace("%Seller%", target != null ? target.getName() : "N/A")
.replace("%seller%", target != null ? target.getName() : "N/A")
.replace("%Time%", time)
.replace("%time%", time));
}
ItemBuilder itemBuilder = ItemBuilder.convertItemStack(data.getString("Items." + ID + ".Item"));
@ -431,7 +500,7 @@ public class GuiListener implements Listener {
inv.setItem(13, getBiddingGlass(player, ID));
inv.setItem(22, new ItemBuilder().setMaterial(config.getString("Settings.GUISettings.OtherSettings.Bid.Item")).setAmount(1)
.setName("Settings.GUISettings.OtherSettings.Bid.Name").setLore(config.getStringList("Settings.GUISettings.OtherSettings.Bid.Lore")).build());
.setName(config.getString("Settings.GUISettings.OtherSettings.Bid.Name")).setLore(config.getStringList("Settings.GUISettings.OtherSettings.Bid.Lore")).build());
inv.setItem(4, getBiddingItem(ID));
@ -455,15 +524,45 @@ public class GuiListener implements Listener {
for (String i : data.getConfigurationSection("Items").getKeys(false)) {
if (data.getString("Items." + i + ".Seller").equalsIgnoreCase(other)) {
List<String> lore = new ArrayList<>();
String price = Methods.getPrice(i, false);
String time = Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"));
OfflinePlayer target = null;
String id = data.getString("Items." + i + ".Seller");
if (id != null) {
target = Methods.getOfflinePlayer(id);
}
OfflinePlayer bidder = null;
String bid = data.getString("Items." + i + ".TopBidder");
if (id != null) {
bidder = Methods.getOfflinePlayer(bid);
}
if (data.getBoolean("Items." + i + ".Biddable")) {
String seller = data.getString("Items." + i + ".Seller");
String topbidder = data.getString("Items." + i + ".TopBidder");
for (String l : config.getStringList("Settings.GUISettings.Bidding")) {
lore.add(l.replace("%TopBid%", Methods.getPrice(i, false)).replace("%topbid%", Methods.getPrice(i, false)).replace("%Seller%", seller).replace("%seller%", seller).replace("%TopBidder%", topbidder).replace("%topbidder%", topbidder).replace("%Time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))));
lore.add(l.replace("%TopBid%", price)
.replace("%topbid%", price)
.replace("%Seller%", target != null ? target.getName() : "N/A")
.replace("%seller%", target != null ? target.getName() : "N/A")
.replace("%TopBidder%", bidder != null ? bidder.getName() : "N/A")
.replace("%topbidder%", bidder != null ? bidder.getName() : "N/A")
.replace("%Time%", time)
.replace("%time%", time));
}
} else {
for (String l : config.getStringList("Settings.GUISettings.SellingItemLore")) {
lore.add(l.replace("%Price%", Methods.getPrice(i, false)).replace("%price%", Methods.getPrice(i, false)).replace("%Seller%", data.getString("Items." + i + ".Seller")).replace("%seller%", data.getString("Items." + i + ".Seller")).replace("%Time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + i + ".Time-Till-Expire"))));
lore.add(l.replace("%Price%", price)
.replace("%price%", price)
.replace("%Seller%", target != null ? target.getName() : "N/A")
.replace("%seller%", target != null ? target.getName() : "N/A")
.replace("%Time%", time)
.replace("%time%", time));
}
}
@ -525,10 +624,15 @@ public class GuiListener implements Listener {
int bid = bidding.get(player.getUniqueId());
String price = Methods.getPrice(ID, false);
if (config.contains("Settings.GUISettings.OtherSettings.Bidding.Lore")) {
List<String> lore = new ArrayList<>();
for (String l : config.getStringList("Settings.GUISettings.OtherSettings.Bidding.Lore")) {
lore.add(l.replace("%Bid%", bid + "").replace("%bid%", bid + "").replace("%TopBid%", Methods.getPrice(ID, false)).replace("%topbid%", Methods.getPrice(ID, false)));
lore.add(l.replace("%Bid%", String.valueOf(bid))
.replace("%bid%", String.valueOf(bid))
.replace("%TopBid%", price)
.replace("%topbid%", price));
}
itemBuilder.setLore(lore);
@ -540,13 +644,35 @@ public class GuiListener implements Listener {
private static ItemStack getBiddingItem(String ID) {
FileConfiguration config = Files.CONFIG.getFile();
FileConfiguration data = Files.DATA.getFile();
String seller = data.getString("Items." + ID + ".Seller");
String topbidder = data.getString("Items." + ID + ".TopBidder");
ItemStack item = Methods.fromBase64(data.getString("Items." + ID + ".Item"));
List<String> lore = new ArrayList<>();
String price = Methods.getPrice(ID, false);
String time = Methods.convertToTime(data.getLong("Items." + ID + ".Time-Till-Expire"));
OfflinePlayer target = null;
String id = data.getString("Items." + ID + ".Seller");
if (id != null) {
target = Methods.getOfflinePlayer(id);
}
OfflinePlayer bidder = null;
String bid = data.getString("Items." + ID + ".TopBidder");
if (bid != null && !bid.equals("None")) {
bidder = Methods.getOfflinePlayer(bid);
}
for (String l : config.getStringList("Settings.GUISettings.Bidding")) {
lore.add(l.replace("%TopBid%", Methods.getPrice(ID, false)).replace("%topbid%", Methods.getPrice(ID, false)).replace("%Seller%", seller).replace("%seller%", seller).replace("%TopBidder%", topbidder).replace("%topbidder%", topbidder).replace("%Time%", Methods.convertToTime(data.getLong("Items." + ID + ".Time-Till-Expire"))).replace("%time%", Methods.convertToTime(data.getLong("Items." + ID + ".Time-Till-Expire"))));
lore.add(l.replace("%TopBid%", price)
.replace("%topbid%", price)
.replace("%Seller%", target != null ? target.getName() : "N/A").replace("%seller%", target != null ? target.getName() : "N/A")
.replace("%TopBidder%", bidder != null ? bidder.getName() : "N/A").replace("%topbidder%", bidder != null ? bidder.getName() : "N/A")
.replace("%Time%", time)
.replace("%time%", time));
}
ItemBuilder itemBuilder = ItemBuilder.convertItemStack(item);
@ -658,21 +784,24 @@ public class GuiListener implements Listener {
return;
}
Bukkit.getPluginManager().callEvent(new AuctionNewBidEvent(player, Methods.fromBase64(data.getString("Items." + ID + ".Item")), bid));
data.set("Items." + ID + ".Price", bid);
data.set("Items." + ID + ".TopBidder", player.getName());
HashMap<String, String> placeholders = new HashMap<>();
data.set("Items." + ID + ".TopBidder", player.getUniqueId().toString());
Map<String, String> placeholders = new HashMap<>();
placeholders.put("%Bid%", bid + "");
player.sendMessage(Messages.BID_MESSAGE.getMessage(placeholders));
Files.DATA.saveFile();
bidding.put(player.getUniqueId(), 0);
player.closeInventory();
playClick(player);
return;
}
HashMap<String, Integer> priceEdits = new HashMap<>();
Map<String, Integer> priceEdits = new HashMap<>();
priceEdits.put("&a+1", 1);
priceEdits.put("&a+10", 10);
priceEdits.put("&a+100", 100);
@ -808,7 +937,7 @@ public class GuiListener implements Listener {
sellerPlayer.sendMessage(Messages.ADMIN_FORCE_CANCELLED_TO_PLAYER.getMessage());
}
AuctionCancelledEvent event = new AuctionCancelledEvent((sellerPlayer != null ? sellerPlayer : Bukkit.getOfflinePlayer(seller)), Methods.fromBase64(data.getString("Items." + ID + ".Item")), Reaons.ADMIN_FORCE_CANCEL);
AuctionCancelledEvent event = new AuctionCancelledEvent((sellerPlayer != null ? sellerPlayer : Methods.getOfflinePlayer(seller)), Methods.fromBase64(data.getString("Items." + ID + ".Item")), Reasons.ADMIN_FORCE_CANCEL);
Bukkit.getPluginManager().callEvent(event);
data.set("OutOfTime/Cancelled." + num + ".Seller", data.getString("Items." + i + ".Seller"));
data.set("OutOfTime/Cancelled." + num + ".Full-Time", data.getLong("Items." + i + ".Full-Time"));
@ -947,17 +1076,25 @@ public class GuiListener implements Listener {
plugin.getServer().getPluginManager().callEvent(new AuctionBuyEvent(player, i, cost));
plugin.getSupport().removeMoney(player, cost);
plugin.getSupport().addMoney(Methods.getOfflinePlayer(seller), cost);
HashMap<String, String> placeholders = new HashMap<>();
placeholders.put("%Price%", Methods.getPrice(ID, false));
placeholders.put("%price%", Methods.getPrice(ID, false));
String price = Methods.getPrice(ID, false);
placeholders.put("%Price%", price);
placeholders.put("%price%", price);
placeholders.put("%Player%", player.getName());
placeholders.put("%player%", player.getName());
player.sendMessage(Messages.BOUGHT_ITEM.getMessage(placeholders));
if (Methods.isOnline(seller) && Methods.getPlayer(seller) != null) {
if (seller != null && Methods.isOnline(seller) && Methods.getPlayer(seller) != null) {
Player sell = Methods.getPlayer(seller);
sell.sendMessage(Messages.PLAYER_BOUGHT_ITEM.getMessage(placeholders));
playSoldSound(sell);
if (sell != null) {
sell.sendMessage(Messages.PLAYER_BOUGHT_ITEM.getMessage(placeholders));
playSoldSound(sell);
}
}
player.getInventory().addItem(i);
@ -1005,7 +1142,7 @@ public class GuiListener implements Listener {
int ID = data.getInt("Items." + i + ".StoreID");
if (id == ID) {
player.sendMessage(Messages.CANCELLED_ITEM.getMessage());
AuctionCancelledEvent event = new AuctionCancelledEvent(player, Methods.fromBase64(data.getString("Items." + i + ".Item")), Reaons.PLAYER_FORCE_CANCEL);
AuctionCancelledEvent event = new AuctionCancelledEvent(player, Methods.fromBase64(data.getString("Items." + i + ".Item")), Reasons.PLAYER_FORCE_CANCEL);
Bukkit.getPluginManager().callEvent(event);
int num = 1;
for (; data.contains("OutOfTime/Cancelled." + num); num++) ;
@ -1064,7 +1201,7 @@ public class GuiListener implements Listener {
int page = Integer.parseInt(e.getView().getTitle().split("#")[1]);
if (data.contains("OutOfTime/Cancelled")) {
for (String i : data.getConfigurationSection("OutOfTime/Cancelled").getKeys(false)) {
if (data.getString("OutOfTime/Cancelled." + i + ".Seller").equalsIgnoreCase(player.getName())) {
if (data.getString("OutOfTime/Cancelled." + i + ".Seller").equalsIgnoreCase(player.getUniqueId().toString())) {
if (Methods.isInvFull(player)) {
player.sendMessage(Messages.INVENTORY_FULL.getMessage());
break;

View File

@ -23,8 +23,8 @@ Settings:
Macro-Dupe: true #Turn to false if you have an issue, but it should patch the bug.
Sounds:
Toggle: false #Disable the clicking sound.
Sound: 'CLICK' #Make sure if you use 1.8 or lower you use the 1.8 sound and 1.9 and up use 1.9 sounds. The default sound is 1.8.
Sold-Item-Sound: 'CLICK'
Sound: 'UI_BUTTON_CLICK' #Make sure if you use 1.8 or lower you use the 1.8 sound and 1.9 and up use 1.9 sounds. The default sound is 1.8.
Sold-Item-Sound: 'UI_BUTTON_CLICK'
#Sounds are found here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html
GUISettings: #Settings for things in the gui.
SellingItemLore: #The lore on items that are being sold.

View File

@ -1,14 +1,19 @@
import com.ryderbelserion.feather.includeProject
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
gradlePluginPortal()
mavenCentral()
}
}
rootProject.name = "CrazyAuctions"
include(":paper")
pluginManagement {
repositories {
maven("https://repo.crazycrew.us/releases")
gradlePluginPortal()
}
}
plugins {
id("com.ryderbelserion.feather-settings") version "0.0.1"
}
listOf("paper").forEach(::includeProject)