update build script

This commit is contained in:
Ryder Belserion 2024-07-11 20:00:03 -04:00
parent 642ad03b22
commit f794bb9409
No known key found for this signature in database
16 changed files with 117 additions and 2398 deletions

20
.gitignore vendored
View File

@ -5,23 +5,7 @@ build
buildSrc/.gradle
buildSrc/build
core/.gradle
core/build
api/.gradle
api/build
paper/.gradle
paper/build
paper/run/
!paper/run/config/paper-global.yml
!paper/run/config/paper-world-defaults.yml
!paper/run/bukkit.yml
!paper/run/eula.txt
!paper/run/ops.json
!paper/run/server.properties
!paper/run/spigot.yml
!run/eula.txt
run
jars

View File

@ -1,23 +1,92 @@
plugins {
alias(libs.plugins.paperweight)
alias(libs.plugins.shadowJar)
alias(libs.plugins.runPaper)
alias(libs.plugins.minotaur)
alias(libs.plugins.hangar)
`java-plugin`
`paper-plugin`
}
val buildNumber: String? = System.getenv("BUILD_NUMBER")
rootProject.version = if (buildNumber != null) "${libs.versions.minecraft.get()}-$buildNumber" else "1.5.1"
rootProject.version = if (buildNumber != null) "${libs.versions.minecraft.get()}-$buildNumber" else "1.6"
val isSnapshot = false
val isSnapshot = true
val content: String = rootProject.file("CHANGELOG.md").readText(Charsets.UTF_8)
subprojects.filter { it.name != "api" }.forEach {
it.project.version = rootProject.version
dependencies {
paperweight.paperDevBundle(libs.versions.paper)
implementation(libs.vital.paper)
compileOnly(libs.placeholderapi)
compileOnly(libs.oraxen)
compileOnly(libs.vault)
compileOnly(fileTree("libs").include("*.jar"))
}
modrinth {
paperweight {
reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION
}
tasks {
runServer {
jvmArgs("-Dnet.kyori.ansi.colorLevel=truecolor")
defaultCharacterEncoding = Charsets.UTF_8.name()
downloadPlugins {
url("https://github.com/EssentialsX/Essentials/releases/download/2.20.1/EssentialsX-2.20.1.jar")
url("https://ci.lucko.me/job/TinyVault/lastSuccessfulBuild/artifact/build/libs/Vault.jar")
url("https://download.luckperms.net/1544/bukkit/loader/LuckPerms-Bukkit-5.4.131.jar")
}
minecraftVersion(libs.versions.minecraft.get())
}
assemble {
dependsOn(reobfJar)
doLast {
copy {
from(reobfJar.get())
into(rootProject.projectDir.resolve("jars"))
}
}
}
shadowJar {
archiveBaseName.set(rootProject.name)
archiveClassifier.set("")
listOf(
"com.ryderbelserion"
).forEach {
relocate(it, "libs.$it")
}
}
processResources {
inputs.properties("name" to rootProject.name)
inputs.properties("version" to project.version)
inputs.properties("group" to project.group)
inputs.properties("apiVersion" to libs.versions.minecraft.get())
inputs.properties("description" to project.properties["description"])
inputs.properties("website" to project.properties["website"])
filesMatching("plugin.yml") {
expand(inputs.properties)
}
}
modrinth {
token.set(System.getenv("MODRINTH_TOKEN"))
projectId.set(rootProject.name.lowercase())
@ -33,13 +102,15 @@ modrinth {
gameVersions.set(listOf(libs.versions.minecraft.get()))
loaders.addAll("paper", "purpur")
loaders.addAll(listOf("purpur", "paper", "folia"))
syncBodyFrom.set(rootProject.file("README.md").readText(Charsets.UTF_8))
autoAddDependsOn.set(false)
detectLoaders.set(false)
}
}
hangarPublish {
hangarPublish {
publications.register("plugin") {
apiKey.set(System.getenv("HANGAR_KEY"))
@ -65,4 +136,5 @@ hangarPublish {
}
}
}
}
}

View File

@ -1,11 +1,11 @@
import com.ryderbelserion.feather.feather
plugins {
id("com.ryderbelserion.feather-logic") version "0.0.1"
id("com.ryderbelserion.feather-logic") version "0.0.4"
`kotlin-dsl`
}
dependencies {
feather("0.0.1")
feather("0.0.4")
}

View File

@ -19,7 +19,7 @@ triumph-cmd = "2.0.0-ALPHA-10"
tirumph-gui = "3.1.7"
jetbrains = "24.1.0"
kyori = "4.17.0"
vital = "1.5.9"
vital = "1.9"
# Paper
paperweight = "1.7.1"

View File

@ -1,100 +0,0 @@
plugins {
alias(libs.plugins.paperweight)
alias(libs.plugins.shadowJar)
alias(libs.plugins.runPaper)
`paper-plugin`
}
base {
archivesName.set(rootProject.name)
}
dependencies {
paperweight.paperDevBundle(libs.versions.paper)
compileOnly(libs.placeholderapi)
compileOnly(libs.oraxen)
compileOnly(libs.vault)
compileOnly(fileTree("libs").include("*.jar"))
}
paperweight {
reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION
}
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()}-paper-api"
version = rootProject.version.toString()
from(component)
}
}
}
runServer {
jvmArgs("-Dnet.kyori.ansi.colorLevel=truecolor")
defaultCharacterEncoding = Charsets.UTF_8.name()
downloadPlugins {
url("https://github.com/EssentialsX/Essentials/releases/download/2.20.1/EssentialsX-2.20.1.jar")
url("https://ci.lucko.me/job/TinyVault/lastSuccessfulBuild/artifact/build/libs/Vault.jar")
url("https://download.luckperms.net/1544/bukkit/loader/LuckPerms-Bukkit-5.4.131.jar")
}
minecraftVersion(libs.versions.minecraft.get())
}
assemble {
dependsOn(reobfJar)
doLast {
copy {
from(reobfJar.get())
into(rootProject.projectDir.resolve("jars"))
}
}
}
shadowJar {
archiveBaseName.set(rootProject.name)
archiveClassifier.set("")
}
processResources {
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(inputs.properties)
}
}
}

View File

@ -1,32 +0,0 @@
settings:
allow-end: false
warn-on-overload: false
permissions-file: permissions.yml
update-folder: update
plugin-profiling: false
connection-throttle: 4000
query-plugins: false
deprecated-verbose: default
shutdown-message: Server Closed
minimum-api: none
use-map-color-cache: true
spawn-limits:
monsters: 70
animals: 10
water-animals: 5
water-ambient: 20
water-underground-creature: 5
axolotls: 5
ambient: 15
chunk-gc:
period-in-ticks: 600
ticks-per:
animal-spawns: 400
monster-spawns: 1
water-spawns: 1
water-ambient-spawns: 1
water-underground-creature-spawns: 1
axolotl-spawns: 1
ambient-spawns: 1
autosave: 6000
aliases: now-in-commands.yml

View File

@ -1,131 +0,0 @@
# This is the global configuration file for Paper.
# As you can see, there's a lot to configure. Some options may impact gameplay, so use
# with caution, and make sure you know what each option does before configuring.
#
# If you need help with the configuration or have any questions related to Paper,
# join us in our Discord or check the docs page.
#
# The world configuration options have been moved inside
# their respective world folder. The files are named paper-world.yml
#
# Docs: https://docs.papermc.io/
# Discord: https://discord.gg/papermc
# Website: https://papermc.io/
_version: 29
block-updates:
disable-chorus-plant-updates: false
disable-mushroom-block-updates: false
disable-noteblock-updates: false
disable-tripwire-updates: false
chunk-loading-advanced:
auto-config-send-distance: true
player-max-concurrent-chunk-generates: 0
player-max-concurrent-chunk-loads: 0
chunk-loading-basic:
player-max-chunk-generate-rate: -1.0
player-max-chunk-load-rate: 100.0
player-max-chunk-send-rate: 75.0
chunk-system:
gen-parallelism: default
io-threads: -1
worker-threads: -1
collisions:
enable-player-collisions: true
send-full-pos-for-hard-colliding-entities: true
commands:
fix-target-selector-tag-completion: true
suggest-player-names-when-null-tab-completions: true
time-command-affects-all-worlds: false
console:
enable-brigadier-completions: true
enable-brigadier-highlighting: true
has-all-permissions: false
item-validation:
book:
author: 8192
page: 16384
title: 8192
book-size:
page-max: 2560
total-multiplier: 0.98
display-name: 8192
lore-line: 8192
resolve-selectors-in-books: false
logging:
deobfuscate-stacktraces: true
messages:
kick:
authentication-servers-down: <lang:multiplayer.disconnect.authservers_down>
connection-throttle: Connection throttled! Please wait before reconnecting.
flying-player: <lang:multiplayer.disconnect.flying>
flying-vehicle: <lang:multiplayer.disconnect.flying>
no-permission: <red>I'm sorry, but you do not have permission to perform this command.
Please contact the server administrators if you believe that this is in error.
use-display-name-in-quit-message: false
misc:
chat-threads:
chat-executor-core-size: -1
chat-executor-max-size: -1
compression-level: default
fix-entity-position-desync: true
load-permissions-yml-before-plugins: true
max-joins-per-tick: 5
region-file-cache-size: 256
strict-advancement-dimension-check: false
use-alternative-luck-formula: false
use-dimension-type-for-custom-spawners: false
packet-limiter:
all-packets:
action: KICK
interval: 7.0
max-packet-rate: 500.0
kick-message: <red><lang:disconnect.exceeded_packet_rate>
overrides:
ServerboundPlaceRecipePacket:
action: DROP
interval: 4.0
max-packet-rate: 5.0
player-auto-save:
max-per-tick: -1
rate: -1
proxies:
bungee-cord:
online-mode: false
proxy-protocol: false
velocity:
enabled: false
online-mode: false
secret: ''
scoreboards:
save-empty-scoreboard-teams: false
track-plugin-scoreboards: false
spam-limiter:
incoming-packet-threshold: 300
recipe-spam-increment: 1
recipe-spam-limit: 20
tab-spam-increment: 1
tab-spam-limit: 500
timings:
enabled: false
hidden-config-entries:
- database
- proxies.velocity.secret
history-interval: 300
history-length: 3600
server-name: Unknown Server
server-name-privacy: false
url: https://timings.aikar.co/
verbose: false
unsupported-settings:
allow-headless-pistons: false
allow-permanent-block-break-exploits: false
allow-piston-duplication: false
allow-tripwire-disarming-exploits: false
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

@ -1,316 +0,0 @@
# This is the world defaults configuration file for Paper.
# As you can see, there's a lot to configure. Some options may impact gameplay, so use
# with caution, and make sure you know what each option does before configuring.
#
# If you need help with the configuration or have any questions related to Paper,
# join us in our Discord or check the docs page.
#
# Configuration options here apply to all worlds, unless you specify overrides inside
# the world-specific config file inside each world folder.
#
# Docs: https://docs.papermc.io/
# Discord: https://discord.gg/papermc
# Website: https://papermc.io/
_version: 31
anticheat:
anti-xray:
enabled: false
engine-mode: 1
hidden-blocks:
- copper_ore
- deepslate_copper_ore
- gold_ore
- deepslate_gold_ore
- iron_ore
- deepslate_iron_ore
- coal_ore
- deepslate_coal_ore
- lapis_ore
- deepslate_lapis_ore
- mossy_cobblestone
- obsidian
- chest
- diamond_ore
- deepslate_diamond_ore
- redstone_ore
- deepslate_redstone_ore
- clay
- emerald_ore
- deepslate_emerald_ore
- ender_chest
lava-obscures: false
max-block-height: 64
replacement-blocks:
- stone
- oak_planks
- deepslate
update-radius: 2
use-permission: false
obfuscation:
items:
hide-durability: false
hide-itemmeta: false
hide-itemmeta-with-visual-effects: false
chunks:
auto-save-interval: default
delay-chunk-unloads-by: 10s
entity-per-chunk-save-limit:
arrow: -1
ender_pearl: -1
experience_orb: -1
fireball: -1
small_fireball: -1
snowball: -1
fixed-chunk-inhabited-time: -1
flush-regions-on-save: false
max-auto-save-chunks-per-tick: 24
prevent-moving-into-unloaded-chunks: false
collisions:
allow-player-cramming-damage: false
allow-vehicle-collisions: true
fix-climbing-bypassing-cramming-rule: false
max-entity-collisions: 8
only-players-collide: false
command-blocks:
force-follow-perm-level: true
permissions-level: 2
entities:
armor-stands:
do-collision-entity-lookups: true
tick: true
behavior:
allow-spider-world-border-climbing: true
baby-zombie-movement-modifier: 0.5
disable-chest-cat-detection: false
disable-creeper-lingering-effect: false
disable-player-crits: false
door-breaking-difficulty:
husk:
- HARD
vindicator:
- NORMAL
- HARD
zombie:
- HARD
zombie_villager:
- HARD
zombified_piglin:
- HARD
ender-dragons-death-always-places-dragon-egg: false
experience-merge-max-value: -1
mobs-can-always-pick-up-loot:
skeletons: false
zombies: false
nerf-pigmen-from-nether-portals: false
parrots-are-unaffected-by-player-movement: false
phantoms-do-not-spawn-on-creative-players: true
phantoms-only-attack-insomniacs: true
phantoms-spawn-attempt-max-seconds: 119
phantoms-spawn-attempt-min-seconds: 60
piglins-guard-chests: true
pillager-patrols:
disable: false
spawn-chance: 0.2
spawn-delay:
per-player: false
ticks: 12000
start:
day: 5
per-player: false
player-insomnia-start-ticks: 72000
should-remove-dragon: false
spawner-nerfed-mobs-should-jump: false
zombie-villager-infection-chance: default
zombies-target-turtle-eggs: true
entities-target-with-follow-range: false
markers:
tick: true
mob-effects:
immune-to-wither-effect:
wither: true
wither-skeleton: true
spiders-immune-to-poison-effect: true
sniffer:
boosted-hatch-time: default
hatch-time: default
spawning:
all-chunks-are-slime-chunks: false
alt-item-despawn-rate:
enabled: false
items:
cobblestone: 300
count-all-mobs-for-spawning: false
creative-arrow-despawn-rate: default
despawn-ranges:
ambient:
hard: 128
soft: 32
axolotls:
hard: 128
soft: 32
creature:
hard: 128
soft: 32
misc:
hard: 128
soft: 32
monster:
hard: 128
soft: 32
underground_water_creature:
hard: 128
soft: 32
water_ambient:
hard: 64
soft: 32
water_creature:
hard: 128
soft: 32
disable-mob-spawner-spawn-egg-transformation: false
duplicate-uuid:
mode: SAFE_REGEN
safe-regen-delete-range: 32
filter-bad-tile-entity-nbt-from-falling-blocks: true
filtered-entity-tag-nbt-paths:
- Pos
- Motion
- SleepingX
- SleepingY
- SleepingZ
iron-golems-can-spawn-in-air: false
monster-spawn-max-light-level: default
non-player-arrow-despawn-rate: default
per-player-mob-spawns: true
scan-for-legacy-ender-dragon: true
skeleton-horse-thunder-spawn-chance: default
slime-spawn-height:
slime-chunk:
maximum: 40.0
surface-biome:
maximum: 70.0
minimum: 50.0
spawn-limits:
ambient: -1
axolotls: -1
creature: -1
monster: -1
underground_water_creature: -1
water_ambient: -1
water_creature: -1
ticks-per-spawn:
ambient: -1
axolotls: -1
creature: -1
monster: -1
underground_water_creature: -1
water_ambient: -1
water_creature: -1
wandering-trader:
spawn-chance-failure-increment: 25
spawn-chance-max: 75
spawn-chance-min: 25
spawn-day-length: 24000
spawn-minute-length: 1200
wateranimal-spawn-height:
maximum: default
minimum: default
tracking-range-y:
animal: default
display: default
enabled: false
misc: default
monster: default
other: default
player: default
environment:
disable-explosion-knockback: false
disable-ice-and-snow: false
disable-teleportation-suffocation-check: false
disable-thunder: false
fire-tick-delay: 30
frosted-ice:
delay:
max: 40
min: 20
enabled: true
generate-flat-bedrock: false
locate-structures-outside-world-border: false
max-block-ticks: 65536
max-fluid-ticks: 65536
nether-ceiling-void-damage-height: disabled
optimize-explosions: false
portal-create-radius: 16
portal-search-radius: 128
portal-search-vanilla-dimension-scaling: true
treasure-maps:
enabled: true
find-already-discovered:
loot-tables: default
villager-trade: false
water-over-lava-flow-speed: 5
feature-seeds:
generate-random-seeds-for-all: false
fishing-time-range:
maximum: 600
minimum: 100
fixes:
disable-unloaded-chunk-enderpearl-exploit: true
falling-block-height-nerf: disabled
fix-items-merging-through-walls: false
prevent-tnt-from-moving-in-water: false
split-overstacked-loot: true
tnt-entity-height-nerf: disabled
hopper:
cooldown-when-full: true
disable-move-event: false
ignore-occluding-blocks: false
lootables:
auto-replenish: false
max-refills: -1
refresh-max: 2d
refresh-min: 12h
reset-seed-on-fill: true
restrict-player-reloot: true
restrict-player-reloot-time: disabled
maps:
item-frame-cursor-limit: 128
item-frame-cursor-update-interval: 10
max-growth-height:
bamboo:
max: 16
min: 11
cactus: 3
reeds: 3
misc:
disable-end-credits: false
disable-relative-projectile-velocity: false
disable-sprint-interruption-on-attack: false
light-queue-size: 20
max-leash-distance: 10.0
redstone-implementation: VANILLA
shield-blocking-delay: 5
show-sign-click-command-failure-msgs-to-player: false
update-pathfinding-on-block-update: true
scoreboards:
allow-non-player-entities-on-scoreboards: true
use-vanilla-world-scoreboard-name-coloring: false
spawn:
allow-using-signs-inside-spawn-protection: false
keep-spawn-loaded: true
keep-spawn-loaded-range: 10
tick-rates:
behavior:
villager:
validatenearbypoi: -1
container-update: 1
dry-farmland: 1
grass-spread: 1
mob-spawner: 1
sensor:
villager:
secondarypoisensor: 40
wet-farmland: 1
unsupported-settings:
disable-world-ticking-when-empty: false
fix-invulnerable-end-crystal-exploit: true

View File

@ -1,3 +0,0 @@
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
#Mon Oct 16 20:19:20 EDT 2023
eula=true

View File

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

View File

@ -1,64 +0,0 @@
#Minecraft server properties
#Tue Jun 25 13:09:57 EDT 2024
accepts-transfers=false
allow-flight=false
allow-nether=false
broadcast-console-to-ops=false
broadcast-rcon-to-ops=false
bug-report-link=
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
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

@ -1,179 +0,0 @@
# This is the main configuration file for Spigot.
# As you can see, there's tons to configure. Some options may impact gameplay, so use
# with caution, and make sure you know what each option does before configuring.
# For a reference for any variable inside this file, check out the Spigot wiki at
# http://www.spigotmc.org/wiki/spigot-configuration/
#
# If you need help with the configuration or have any questions related to Spigot,
# join us at the Discord or drop by our forums and leave a post.
#
# Discord: https://www.spigotmc.org/go/discord
# Forums: http://www.spigotmc.org/
settings:
debug: false
timeout-time: 60
restart-on-crash: false
restart-script: ./start.sh
save-user-cache-on-stop-only: false
moved-too-quickly-multiplier: 10.0
moved-wrongly-threshold: 0.0625
player-shuffle: 0
user-cache-size: 1000
netty-threads: 4
attribute:
maxHealth:
max: 2048.0
movementSpeed:
max: 2048.0
attackDamage:
max: 2048.0
log-villager-deaths: false
log-named-deaths: false
sample-count: 12
bungeecord: false
messages:
restart: Server is restarting
whitelist: You are not whitelisted on this server!
unknown-command: Unknown command. Type "/help" for help.
server-full: The server is full!
outdated-client: Outdated client! Please use {0}
outdated-server: Outdated server! I'm still on {0}
advancements:
disable-saving: true
disabled:
- minecraft:story/disabled
commands:
silent-commandblock-console: false
spam-exclusions:
- /skill
replace-commands:
- setblock
- summon
- testforblock
- tellraw
log: true
tab-complete: 0
send-namespaced: true
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
dragon-death-sound-radius: 0
wither-spawn-sound-radius: 0
end-portal-sound-radius: 0
zombie-aggressive-towards-villager: true
entity-activation-range:
animals: 32
monsters: 32
raiders: 48
misc: 16
water: 16
villagers: 32
flying-monsters: 32
wake-up-inactive:
animals-max-per-tick: 4
animals-every: 1200
animals-for: 100
monsters-max-per-tick: 8
monsters-every: 400
monsters-for: 100
villagers-max-per-tick: 4
villagers-every: 600
villagers-for: 100
flying-monsters-max-per-tick: 8
flying-monsters-every: 200
flying-monsters-for: 100
villagers-work-immunity-after: 100
villagers-work-immunity-for: 20
villagers-active-for-panic: true
tick-inactive-villagers: true
ignore-spectators: false
seed-village: 10387312
seed-desert: 14357617
seed-igloo: 14357618
seed-jungle: 14357619
seed-swamp: 14357620
seed-monument: 10387313
seed-shipwreck: 165745295
seed-ocean: 14357621
seed-outpost: 165745296
seed-endcity: 10387313
seed-slime: 987234911
seed-nether: 30084232
seed-mansion: 10387319
seed-fossil: 14357921
seed-portal: 34222645
seed-ancientcity: 20083232
seed-trailruins: 83469867
seed-buriedtreasure: 10387320
seed-mineshaft: default
seed-stronghold: default
entity-tracking-range:
players: 48
animals: 48
monsters: 48
misc: 32
display: 128
other: 64
ticks-per:
hopper-transfer: 8
hopper-check: 1
hopper-amount: 1
hopper-can-load-chunks: false
max-tnt-per-tick: 100
max-tick-time:
tile: 50
entity: 50
hunger:
jump-walk-exhaustion: 0.05
jump-sprint-exhaustion: 0.2
combat-exhaustion: 0.1
regen-exhaustion: 6.0
swim-multiplier: 0.01
sprint-multiplier: 0.1
other-multiplier: 0.0
enable-zombie-pigmen-portal-spawns: true
thunder-chance: 100000
growth:
cactus-modifier: 100
cane-modifier: 100
melon-modifier: 100
mushroom-modifier: 100
pumpkin-modifier: 100
sapling-modifier: 100
beetroot-modifier: 100
carrot-modifier: 100
potato-modifier: 100
torchflower-modifier: 100
wheat-modifier: 100
netherwart-modifier: 100
vine-modifier: 100
cocoa-modifier: 100
bamboo-modifier: 100
sweetberry-modifier: 100
kelp-modifier: 100
twistingvines-modifier: 100
weepingvines-modifier: 100
cavevines-modifier: 100
glowberry-modifier: 100
pitcherplant-modifier: 100
mob-spawn-range: 8
simulation-distance: default
merge-radius:
item: 2.5
exp: 3.0
arrow-despawn-rate: 1200
trident-despawn-rate: 1200
view-distance: default
item-despawn-rate: 6000
nerf-spawner-mobs: false
verbose: false
config-version: 12
stats:
disable-saving: false
forced-stats: {}

View File

@ -1,955 +0,0 @@
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

@ -1,505 +0,0 @@
package com.badbones69.crazyauctions.api;
import com.badbones69.crazyauctions.CrazyAuctions;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
public class FileManager {
@NotNull
private final CrazyAuctions plugin = CrazyAuctions.get();
private final HashMap<Files, File> files = new HashMap<>();
private final List<String> homeFolders = new ArrayList<>();
private final List<CustomFile> customFiles = new ArrayList<>();
private final HashMap<String, String> jarHomeFolders = new HashMap<>();
private final HashMap<String, String> autoGenerateFiles = new HashMap<>();
private final HashMap<Files, FileConfiguration> configurations = new HashMap<>();
/**
* Sets up the plugin and loads all necessary files.
*/
public FileManager setup() {
if (!this.plugin.getDataFolder().exists()) this.plugin.getDataFolder().mkdirs();
this.files.clear();
this.customFiles.clear();
this.configurations.clear();
// Loads all the normal static files.
for (Files file : Files.values()) {
File newFile = new File(this.plugin.getDataFolder(), file.getFileLocation());
if (this.plugin.isLogging()) this.plugin.getLogger().info("Loading the " + file.getFileName());
if (!newFile.exists()) {
try (InputStream jarFile = getClass().getResourceAsStream("/" + file.getFileJar())) {
File serverFile = new File(this.plugin.getDataFolder(), "/" + file.getFileLocation());
copyFile(jarFile, serverFile);
} catch (Exception exception) {
this.plugin.getLogger().log(Level.WARNING, "Failed to load file: " + file.getFileName(), exception);
continue;
}
}
this.files.put(file, newFile);
if (file.getFileName().endsWith(".yml")) this.configurations.put(file, YamlConfiguration.loadConfiguration(newFile));
if (this.plugin.isLogging()) this.plugin.getLogger().info("Successfully loaded " + file.getFileName());
}
// Starts to load all the custom files.
if (!this.homeFolders.isEmpty()) {
if (this.plugin.isLogging()) this.plugin.getLogger().info("Loading custom files.");
for (String homeFolder : this.homeFolders) {
File homeFile = new File(this.plugin.getDataFolder(), "/" + homeFolder);
if (homeFile.exists()) {
String[] list = homeFile.list();
if (list != null) {
for (String name : list) {
if (name.endsWith(".yml")) {
CustomFile file = new CustomFile(name, homeFolder);
if (file.exists()) {
this.customFiles.add(file);
if (this.plugin.isLogging()) this.plugin.getLogger().info("Loaded new custom file: " + homeFolder + "/" + name + ".");
}
}
}
}
} else {
homeFile.mkdir();
if (this.plugin.isLogging()) this.plugin.getLogger().info("The folder " + homeFolder + "/ was not found so it was created.");
for (String fileName : this.autoGenerateFiles.keySet()) {
if (this.autoGenerateFiles.get(fileName).equalsIgnoreCase(homeFolder)) {
homeFolder = this.autoGenerateFiles.get(fileName);
try (InputStream jarFile = getClass().getResourceAsStream((this.jarHomeFolders.getOrDefault(fileName, homeFolder)) + "/" + fileName)) {
File serverFile = new File(this.plugin.getDataFolder(), homeFolder + "/" + fileName);
copyFile(jarFile, serverFile);
if (fileName.toLowerCase().endsWith(".yml")) this.customFiles.add(new CustomFile(fileName, homeFolder));
if (this.plugin.isLogging()) this.plugin.getLogger().info("Created new default file: " + homeFolder + "/" + fileName + ".");
} catch (Exception exception) {
this.plugin.getLogger().log(Level.SEVERE, "Failed to create new default file: " + homeFolder + "/" + fileName + "!", exception);
}
}
}
}
}
if (this.plugin.isLogging()) this.plugin.getLogger().info("Finished loading custom files.");
}
return this;
}
/**
* Register a folder that has custom files in it. Make sure to have a "/" in front of the folder name.
* @param homeFolder The folder that has custom files in it.
*/
public FileManager registerCustomFilesFolder(String homeFolder) {
this.homeFolders.add(homeFolder);
return this;
}
/**
* Unregister a folder that has custom files in it. Make sure to have a "/" in front of the folder name.
* @param homeFolder The folder with custom files in it.
*/
public FileManager unregisterCustomFilesFolder(String homeFolder) {
this.homeFolders.remove(homeFolder);
return this;
}
/**
* Register a file that needs to be generated when it's home folder doesn't exist. Make sure to have a "/" in front of the home folder's name.
* @param fileName The name of the file you want to auto-generate when the folder doesn't exist.
* @param homeFolder The folder that has custom files in it.
*/
public FileManager registerDefaultGenerateFiles(String fileName, String homeFolder) {
this.autoGenerateFiles.put(fileName, homeFolder);
return this;
}
/**
* Register a file that needs to be generated when it's home folder doesn't exist. Make sure to have a "/" in front of the home folder's name.
* @param fileName The name of the file you want to auto-generate when the folder doesn't exist.
* @param homeFolder The folder that has custom files in it.
* @param jarHomeFolder The folder that the file is found in the jar.
*/
public FileManager registerDefaultGenerateFiles(String fileName, String homeFolder, String jarHomeFolder) {
this.autoGenerateFiles.put(fileName, homeFolder);
this.jarHomeFolders.put(fileName, jarHomeFolder);
return this;
}
/**
* Unregister a file that doesn't need to be generated when it's home folder doesn't exist. Make sure to have a "/" in front of the home folder's name.
* @param fileName The file that you want to remove from auto-generating.
*/
public FileManager unregisterDefaultGenerateFiles(String fileName) {
this.autoGenerateFiles.remove(fileName);
this.jarHomeFolders.remove(fileName);
return this;
}
/**
* Gets the file from the system.
* @return The file from the system.
*/
public FileConfiguration getFile(Files file) {
return this.configurations.get(file);
}
/**
* Get a custom file from the loaded custom files instead of a hardcoded one.
* This allows you to get custom files like Per player data files.
* @param name Name of the crate you want. (Without the .yml)
* @return The custom file you wanted otherwise if not found will return null.
*/
public CustomFile getFile(String name) {
for (CustomFile file : this.customFiles) {
if (file.getName().equalsIgnoreCase(name)) {
return file;
}
}
return null;
}
public void removeFile(String name) {
this.customFiles.remove(getFile(name));
}
public void addFile(String name, String folder) {
this.customFiles.add(new CustomFile(name, folder));
}
/**
* Saves the file from the loaded state to the file system.
*/
public void saveFile(Files file) {
try {
this.configurations.get(file).save(this.files.get(file));
} catch (IOException exception) {
this.plugin.getLogger().log(Level.SEVERE, "Could not save " + file.getFileName() + "!", exception);
}
}
/**
* Save a custom file.
* @param name The name of the custom file.
*/
public void saveFile(String name) {
CustomFile file = getFile(name);
if (file == null) {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("The file " + name + ".yml could not be found!");
return;
}
try {
file.getFile().save(new File(this.plugin.getDataFolder(), file.getHomeFolder() + "/" + file.getFileName()));
if (this.plugin.isLogging()) this.plugin.getLogger().info("Successfully saved the " + file.getFileName() + ".");
} catch (Exception exception) {
this.plugin.getLogger().log(Level.SEVERE, "Could not save " + file.getFileName() + "!", exception);
}
}
/**
* Save a custom file.
*
* @param file The custom file you are saving.
*/
public void saveFile(CustomFile file) {
file.saveFile();
}
/**
* Overrides the loaded state file and loads the file systems file.
*/
public void reloadFile(Files file) {
if (file.getFileName().endsWith(".yml")) this.configurations.put(file, YamlConfiguration.loadConfiguration(this.files.get(file)));
}
/**
* Overrides the loaded state file and loads the file systems file.
*/
public void reloadFile(String name) {
CustomFile file = getFile(name);
if (file != null) {
try {
file.file = YamlConfiguration.loadConfiguration(new File(this.plugin.getDataFolder(), "/" + file.getHomeFolder() + "/" + file.getFileName()));
if (this.plugin.isLogging()) this.plugin.getLogger().info("Successfully reloaded the " + file.getFileName() + ".");
} catch (Exception exception) {
this.plugin.getLogger().log(Level.SEVERE, "Could not reload the " + file.getFileName() + "!", exception);
}
} else {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("The file " + name + ".yml could not be found!");
}
}
/**
* Overrides the loaded state file and loads the filesystems file.
*/
public void reloadFile(CustomFile file) {
file.reloadFile();
}
public void reloadAllFiles() {
for (Files file : Files.values()) {
file.reloadFile();
}
for (CustomFile file : this.customFiles) {
file.reloadFile();
}
}
public List<String> getAllCratesNames() {
List<String> files = new ArrayList<>();
String[] file = new File(this.plugin.getDataFolder(), "/crates").list();
if (file != null) {
for (String name : file) {
if (!name.endsWith(".yml")) continue;
files.add(name.replaceAll(".yml", ""));
}
}
return files;
}
/**
* Was found here: <a href="https://bukkit.org/threads/extracting-file-from-jar.16962">...</a>
*/
private void copyFile(InputStream in, File out) throws Exception {
try (InputStream fis = in; FileOutputStream fos = new FileOutputStream(out)) {
byte[] buf = new byte[1024];
int i;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
}
}
public enum Files {
// ENUM_NAME("fileName.yml", "fileLocation.yml"),
// ENUM_NAME("fileName.yml", "newFileLocation.yml", "oldFileLocation.yml"),
CONFIG("config.yml", "config.yml"),
MESSAGES("messages.yml", "messages.yml"),
TEST_FILE("test-file.yml", "test-file.yml"),
DATA("data.yml", "data.yml");
private final String fileName;
private final String fileJar;
private final String fileLocation;
@NotNull
private final CrazyAuctions plugin = CrazyAuctions.get();
@NotNull
private final FileManager fileManager = this.plugin.getFileManager();
/**
* The files that the server will try and load.
* @param fileName The file name that will be in the plugin's folder.
* @param fileLocation The location the file in the plugin's folder.
*/
Files(String fileName, String fileLocation) {
this(fileName, fileLocation, fileLocation);
}
/**
* The files that the server will try and load.
* @param fileName The file name that will be in the plugin's folder.
* @param fileLocation The location of the file will be in the plugin's folder.
* @param fileJar The location of the file in the jar.
*/
Files(String fileName, String fileLocation, String fileJar) {
this.fileName = fileName;
this.fileLocation = fileLocation;
this.fileJar = fileJar;
}
/**
* Get the name of the file.
* @return The name of the file.
*/
public String getFileName() {
return this.fileName;
}
/**
* The location the jar it is at.
* @return The location in the jar the file is in.
*/
public String getFileLocation() {
return this.fileLocation;
}
/**
* Get the location of the file in the jar.
* @return The location of the file in the jar.
*/
public String getFileJar() {
return this.fileJar;
}
/**
* Gets the file from the system.
* @return The file from the system.
*/
public FileConfiguration getFile() {
return this.fileManager.getFile(this);
}
/**
* Saves the file from the loaded state to the file system.
*/
public void saveFile() {
this.fileManager.saveFile(this);
}
/**
* Overrides the loaded state file and loads the file systems file.
*/
public void reloadFile() {
if (this.getFileName().endsWith(".yml")) this.fileManager.reloadFile(this);
}
}
public static class CustomFile {
private final String name;
private final String fileName;
private final String homeFolder;
private FileConfiguration file;
@NotNull
private final CrazyAuctions plugin = CrazyAuctions.get();
/**
* A custom file that is being made.
* @param name Name of the file.
* @param homeFolder The home folder of the file.
*/
public CustomFile(String name, String homeFolder) {
this.name = name.replace(".yml", "");
this.fileName = name;
this.homeFolder = homeFolder;
if (new File(this.plugin.getDataFolder(), "/" + homeFolder).exists()) {
if (new File(this.plugin.getDataFolder(), "/" + homeFolder + "/" + name).exists()) {
this.file = YamlConfiguration.loadConfiguration(new File(this.plugin.getDataFolder(), "/" + homeFolder + "/" + name));
} else {
this.file = null;
}
} else {
new File(this.plugin.getDataFolder(), "/" + homeFolder).mkdir();
if (this.plugin.isLogging()) this.plugin.getLogger().info("The folder " + homeFolder + "/ was not found so it was created.");
this.file = null;
}
}
/**
* Get the name of the file without the .yml part.
* @return The name of the file without the .yml.
*/
public String getName() {
return this.name;
}
/**
* Get the full name of the file.
* @return Full name of the file.
*/
public String getFileName() {
return this.fileName;
}
/**
* Get the name of the home folder of the file.
* @return The name of the home folder the files are in.
*/
public String getHomeFolder() {
return this.homeFolder;
}
/**
* Get the ConfigurationFile.
* @return The ConfigurationFile of this file.
*/
public FileConfiguration getFile() {
return this.file;
}
/**
* Check if the file actually exists in the file system.
* @return True if it does and false if it doesn't.
*/
public boolean exists() {
return this.file != null;
}
/**
* Save the custom file.
*/
public void saveFile() {
if (this.file != null) {
try {
this.file.save(new File(this.plugin.getDataFolder(), this.homeFolder + "/" + this.fileName));
if (this.plugin.isLogging()) plugin.getLogger().info("Successfully saved the " + this.fileName + ".");
} catch (Exception exception) {
this.plugin.getLogger().log(Level.WARNING, "Could not save " + this.fileName + "!", exception);
}
} else {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("There was a null custom file that could not be found!");
}
}
/**
* Overrides the loaded state file and loads the filesystems file.
*/
public void reloadFile() {
if (this.file != null) {
try {
this.file = YamlConfiguration.loadConfiguration(new File(this.plugin.getDataFolder(), "/" + this.homeFolder + "/" + this.fileName));
if (this.plugin.isLogging()) this.plugin.getLogger().info("Successfully reloaded the " + this.fileName + ".");
} catch (Exception exception) {
this.plugin.getLogger().log(Level.SEVERE, "Could not reload the " + this.fileName + "!", exception);
}
} else {
if (this.plugin.isLogging()) this.plugin.getLogger().warning("There was a null custom file that was not found!");
}
}
}
}

View File

@ -1,32 +0,0 @@
package com.badbones69.crazyauctions.api.support;
import com.badbones69.crazyauctions.CrazyAuctions;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
public enum PluginSupport {
DECENT_HOLOGRAMS("DecentHolograms"),
HOLOGRAPHIC_DISPLAYS("HolographicDisplays"),
VAULT("Vault"),
CMI("CMI"),
PLACEHOLDERAPI("PlaceholderAPI"),
ORAXEN("Oraxen"),
ITEMS_ADDER("ItemsAdder");
private final String name;
private final @NotNull CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class);
PluginSupport(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public boolean isPluginEnabled() {
return this.plugin.getServer().getPluginManager().isPluginEnabled(this.name);
}
}

View File

@ -1,7 +1,3 @@
import com.ryderbelserion.feather.includeProject
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
rootProject.name = "CrazyAuctions"
pluginManagement {
@ -13,7 +9,5 @@ pluginManagement {
}
plugins {
id("com.ryderbelserion.feather-settings") version "0.0.1"
id("com.ryderbelserion.feather-settings") version "0.0.4"
}
listOf("paper").forEach(::includeProject)