Initial commit

This commit is contained in:
Ilya 2022-11-15 00:42:00 +03:00
commit 72cde6640c
31 changed files with 1597 additions and 0 deletions

136
.gitignore vendored Executable file
View File

@ -0,0 +1,136 @@
Server/world/
Server/world_the_end/
Server/world_nether/
Server/logs/
Server/banned-ips.json
Server/banned-players.json
Server/commands.yml
Server/help.yml
Server/ops.json
Server/permissions.yml
Server/plugins/
Server/usercache.json
Server/version_history.json
Server/wepif.yml
Server/whitelist.json
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Cache of project
.gradletasknamecache
**/build/
# Common working directory
run/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
!Server/*.jar
!Server/plugins/*.jar

37
Server/bukkit.yml Executable file
View File

@ -0,0 +1,37 @@
# This is the main configuration file for Bukkit.
# As you can see, there's actually not that much to configure without any plugins.
# For a reference for any variable inside this file, check out the Bukkit Wiki at
# http://wiki.bukkit.org/Bukkit.yml
#
# If you need help on this file, feel free to join us on irc or leave a message
# on the forums asking for advice.
#
# IRC: #spigot @ irc.spi.gt
# (If this means nothing to you, just go to http://www.spigotmc.org/pages/irc/ )
# Forums: http://www.spigotmc.org/
# Bug tracker: http://www.spigotmc.org/go/bugs
settings:
allow-end: true
warn-on-overload: true
permissions-file: permissions.yml
update-folder: update
plugin-profiling: false
connection-throttle: 4000
query-plugins: true
deprecated-verbose: default
shutdown-message: Server closed
spawn-limits:
monsters: 70
animals: 15
water-animals: 5
ambient: 15
chunk-gc:
period-in-ticks: 600
load-threshold: 0
ticks-per:
animal-spawns: 400
monster-spawns: 1
autosave: 6000
aliases: now-in-commands.yml

4
Server/eula.txt Executable file
View File

@ -0,0 +1,4 @@
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
#and also agreeing that tacos are tasty.
#Mon Dec 21 15:24:20 MSK 2020
eula=true

BIN
Server/paper-1.12.2-1618.jar Executable file

Binary file not shown.

183
Server/paper.yml Executable file
View File

@ -0,0 +1,183 @@
# This is the main configuration file for Paper.
# 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.
#
# If you need help with the configuration or have any questions related to Paper,
# join us in our IRC channel.
#
# IRC: #paper @ irc.spi.gt ( http://irc.spi.gt/iris/?channels=paper )
# Wiki: https://paper.readthedocs.org/
# Paper Forums: https://aquifermc.org/
verbose: false
config-version: 13
settings:
enable-player-collisions: true
player-auto-save-rate: -1
max-player-auto-save-per-tick: -1
load-permissions-yml-before-plugins: true
bungee-online-mode: true
save-player-data: true
min-chunk-load-threads: 2
book-size:
page-max: 2560
total-multiplier: 0.98
spam-limiter:
tab-spam-increment: 10
tab-spam-limit: 500
use-alternative-luck-formula: false
remove-invalid-statistics: false
region-file-cache-size: 256
incoming-packet-spam-threshold: 300
sleep-between-chunk-saves: false
save-empty-scoreboard-teams: false
suggest-player-names-when-null-tab-completions: true
watchdog:
early-warning-every: 5000
early-warning-delay: 10000
timings:
enabled: true
verbose: true
server-name-privacy: false
hidden-config-entries:
- database
- settings.bungeecord-addresses
history-interval: 300
history-length: 3600
messages:
kick:
authentication-servers-down: ''
flying-player: Flying is not enabled on this server
flying-vehicle: Flying is not enabled on this server
world-settings:
default:
keep-spawn-loaded-range: 8
auto-save-interval: -1
frosted-ice:
enabled: true
delay:
min: 20
max: 40
grass-spread-tick-rate: 1
game-mechanics:
disable-sprint-interruption-on-attack: false
disable-chest-cat-detection: false
disable-end-credits: false
shield-blocking-delay: 5
disable-player-crits: false
disable-unloaded-chunk-enderpearl-exploit: true
village-sieges-enabled: true
allow-permanent-chunk-loaders: false
scan-for-legacy-ender-dragon: true
elytra-hit-wall-damage: true
nether-ceiling-void-damage: false
allow-non-player-entities-on-scoreboards: false
container-update-tick-rate: 1
hopper:
push-based: false
cooldown-when-full: true
disable-move-event: false
parrots-are-unaffected-by-player-movement: false
disable-explosion-knockback: false
use-alternate-fallingblock-onGround-detection: false
non-player-arrow-despawn-rate: -1
prevent-tnt-from-moving-in-water: false
keep-spawn-loaded: true
fire-physics-event-for-redstone: false
disable-ice-and-snow: false
armor-stands-do-collision-entity-lookups: true
skeleton-horse-thunder-spawn-chance: 0.01
spawner-nerfed-mobs-should-jump: false
baby-zombie-movement-speed: 0.5
allow-leashing-undead-horse: false
all-chunks-are-slime-chunks: false
squid-spawn-height:
maximum: 0.0
mob-spawner-tick-rate: 1
bed-search-radius: 1
armor-stands-tick: true
experience-merge-max-value: -1
anti-xray:
enabled: false
engine-mode: 1
chunk-edge-mode: 1
max-chunk-section-index: 3
update-radius: 2
hidden-blocks:
- gold_ore
- iron_ore
- coal_ore
- lapis_ore
- mossy_cobblestone
- obsidian
- chest
- diamond_ore
- redstone_ore
- lit_redstone_ore
- clay
- emerald_ore
- ender_chest
replacement-blocks:
- stone
- planks
disable-thunder: false
enable-treasure-maps: true
treasure-maps-return-already-discovered: false
disable-teleportation-suffocation-check: false
generator-settings:
canyon: true
caves: true
dungeon: true
fortress: true
mineshaft: true
monument: true
stronghold: true
temple: true
village: true
flat-bedrock: false
disable-extreme-hills-emeralds: false
disable-extreme-hills-monster-eggs: false
disable-mesa-additional-gold: false
skip-entity-ticking-in-chunks-scheduled-for-unload: true
use-vanilla-world-scoreboard-name-coloring: false
falling-block-height-nerf: 0
tnt-entity-height-nerf: 0
use-chunk-inhabited-timer: true
fast-drain:
lava: false
water: false
despawn-ranges:
soft: 32
hard: 128
lava-flow-speed:
normal: 30
nether: 10
fishing-time-range:
MinimumTicks: 100
MaximumTicks: 600
remove-corrupt-tile-entities: false
prevent-moving-into-unloaded-chunks: false
max-entity-collisions: 8
duplicate-uuid-resolver: saferegen
duplicate-uuid-saferegen-delete-range: 32
disable-creeper-lingering-effect: false
filter-nbt-data-from-spawn-eggs-and-related: true
queue-light-updates: false
optimize-explosions: false
save-queue-limit-for-auto-save: 50
delay-chunk-unloads-by: 10s
max-auto-save-chunks-per-tick: 24
max-chunk-sends-per-tick: 81
max-growth-height:
cactus: 3
reeds: 3
max-chunk-gens-per-tick: 10
water-over-lava-flow-speed: 5
lootables:
auto-replenish: false
restrict-player-reloot: true
reset-seed-on-fill: true
max-refills: -1
refresh-min: 12h
refresh-max: 2d
portal-search-radius: 128

Binary file not shown.

BIN
Server/plugins/Economy.jar Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Server/plugins/PowerNBT.jar Executable file

Binary file not shown.

BIN
Server/plugins/QSeller-1.0.0.jar Executable file

Binary file not shown.

BIN
Server/plugins/Vault (1).jar Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

39
Server/server.properties Executable file
View File

@ -0,0 +1,39 @@
#Minecraft server properties
#Sun Feb 27 14:13:20 MSK 2022
spawn-protection=16
generator-settings=
force-gamemode=false
allow-nether=true
gamemode=0
broadcast-console-to-ops=true
enable-query=false
player-idle-timeout=0
difficulty=1
spawn-monsters=true
op-permission-level=4
pvp=true
snooper-enabled=true
level-type=DEFAULT
hardcore=false
enable-command-block=true
max-players=20
network-compression-threshold=256
resource-pack-sha1=
max-world-size=29999984
server-port=25565
debug=false
server-ip=
spawn-npcs=true
allow-flight=false
level-name=world
view-distance=10
resource-pack=
spawn-animals=true
white-list=false
generate-structures=true
online-mode=false
max-build-height=256
level-seed=
prevent-proxy-connections=false
enable-rcon=false
motd=A Minecraft Server

126
Server/spigot.yml Executable file
View File

@ -0,0 +1,126 @@
# 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 IRC or drop by our forums and leave a post.
#
# IRC: #spigot @ irc.spi.gt ( http://www.spigotmc.org/pages/irc/ )
# Forums: http://www.spigotmc.org/
config-version: 11
settings:
sample-count: 12
save-user-cache-on-stop-only: false
moved-wrongly-threshold: 0.0625
moved-too-quickly-multiplier: 10.0
filter-creative-items: true
player-shuffle: 0
attribute:
maxHealth:
max: 2048.0
movementSpeed:
max: 2048.0
attackDamage:
max: 2048.0
user-cache-size: 1000
late-bind: false
int-cache-limit: 1024
item-dirty-ticks: 20
netty-threads: 4
bungeecord: false
timeout-time: 60
restart-on-crash: true
restart-script: ./start.sh
debug: false
commands:
tab-complete: 0
silent-commandblock-console: false
log: true
replace-commands:
- setblock
- summon
- testforblock
- tellraw
spam-exclusions:
- /skill
messages:
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}
restart: Server is restarting
advancements:
disable-saving: false
disabled:
- minecraft:story/disabled
stats:
disable-saving: false
forced-stats: {}
world-settings:
default:
verbose: true
item-despawn-rate: 6000
merge-radius:
item: 2.5
exp: 3.0
view-distance: 10
enable-zombie-pigmen-portal-spawns: true
wither-spawn-sound-radius: 0
hanging-tick-frequency: 100
zombie-aggressive-towards-villager: true
arrow-despawn-rate: 1200
nerf-spawner-mobs: false
entity-tracking-range:
players: 48
animals: 48
monsters: 48
misc: 32
other: 64
entity-activation-range:
animals: 32
monsters: 32
misc: 16
water: 16
tick-inactive-villagers: true
max-tick-time:
tile: 50
entity: 50
ticks-per:
hopper-transfer: 8
hopper-check: 1
hopper-amount: 1
random-light-updates: false
mob-spawn-range: 4
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
save-structure-info: true
growth:
cactus-modifier: 100
cane-modifier: 100
melon-modifier: 100
mushroom-modifier: 100
pumpkin-modifier: 100
sapling-modifier: 100
wheat-modifier: 100
netherwart-modifier: 100
vine-modifier: 100
cocoa-modifier: 100
max-tnt-per-tick: 100
squid-spawn-range:
min: 45.0
seed-village: 10387312
seed-feature: 14357617
seed-monument: 10387313
seed-slime: 987234911
dragon-death-sound-radius: 0
max-entity-collisions: 8

75
build.gradle Executable file
View File

@ -0,0 +1,75 @@
plugins {
id 'java'
}
group = 'ru.redguy'
version = '1.0.0'
repositories {
mavenCentral()
maven {
name = 'papermc-repo'
url = 'https://papermc.io/repo/repository/maven-public/'
}
maven {
name = 'sonatype'
url = 'https://oss.sonatype.org/content/groups/public/'
}
maven {
name = 'redguy-repo'
url = 'https://repo.redguy.ru/repository/maven-public/'
}
}
dependencies {
compileOnly 'com.destroystokyo.paper:paper-api:1.12.2-R0.1-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.11.1'
compileOnly "com.github.MilkBowl:VaultAPI:1.7"
compileOnly "net.citizensnpcs:citizensapi:2.0.29-SNAPSHOT"
implementation 'com.github.IPVP-MC:canvas:1fa1956b89'
implementation 'mysql:mysql-connector-java:8.0.16'
implementation 'com.zaxxer:HikariCP:4.0.3'
implementation 'org.jetbrains:annotations:20.1.0'
implementation 'com.h2database:h2:1.4.200'
}
def targetJavaVersion = 8
java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
if (JavaVersion.current() < javaVersion) {
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
}
}
compileJava.options.encoding = 'UTF-8'
tasks.withType(JavaCompile).configureEach {
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
options.release = targetJavaVersion
}
}
jar {
configurations.implementation.canBeResolved = true
from {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
configurations.implementation.collect { it.isDirectory() ? it : zipTree(it) }
}
}
processResources {
def props = [version: version]
inputs.properties props
filteringCharset 'UTF-8'
filesMatching('plugin.yml') {
expand props
}
}
task copytorun(type: Copy) {
delete file("$projectDir/Server/plugins/QSeller*")
from file("$projectDir/build/libs/QSeller-${version}.jar")
into file("$projectDir/Server/plugins/")
}

0
gradle.properties Executable file
View File

BIN
gradle/wrapper/gradle-wrapper.jar vendored Executable file

Binary file not shown.

5
gradle/wrapper/gradle-wrapper.properties vendored Executable file
View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Executable file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Executable file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle Executable file
View File

@ -0,0 +1 @@
rootProject.name = 'QSeller'

View File

@ -0,0 +1,126 @@
package ru.redguy.qseller;
import com.zaxxer.hikari.HikariDataSource;
import org.bukkit.Material;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
public abstract class Database {
protected static Database instance;
public static Database getInstance() {
return instance;
}
private HikariDataSource ds;
private final String prefix;
protected Database(HikariDataSource ds, String tablePrefix) {
this.ds = ds;
prefix = tablePrefix;
dataBaseCheck();
}
abstract boolean isTableExists(String name, Connection con) throws SQLException;
private void dataBaseCheck() {
try (Connection con = ds.getConnection()) {
if (!isTableExists("OPTIONS", con)) {
PreparedStatement ps = con.prepareStatement("CREATE TABLE " + prefix + "options (option_name text not null,option_value text null);");
ps.execute();
ps = con.prepareStatement("INSERT INTO " + prefix + "options (option_name, option_value) VALUES ('schema_version', '1');");
ps.execute();
}
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + prefix + "options WHERE option_name = 'schema_version';");
ResultSet rs = ps.executeQuery();
rs.next();
String schema_version = rs.getString("option_value");
switch (schema_version) {
case "1": {
if (!isTableExists("players", con)) {
ps = con.prepareStatement("create table " + prefix + "players (uuid text not null,villager_level int default 1 null);");
ps.execute();
}
if (!isTableExists("items", con)) {
ps = con.prepareStatement("create table " + prefix + "items (player text not null,item text not null,sold int default 0 not null);");
ps.execute();
}
break;
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public String getPrefix() {
return prefix;
}
public void disconnect() {
this.ds.close();
}
public int getVillagerLevel(UUID uuid) {
try (Connection con = ds.getConnection()) {
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + prefix + "players WHERE uuid = ?");
ps.setString(1, uuid.toString());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return rs.getInt("villager_level");
}
ps = con.prepareStatement("INSERT INTO " + prefix + "players (uuid) VALUES (?)");
ps.setString(1, uuid.toString());
ps.execute();
return getVillagerLevel(uuid);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return -1;
}
public int getItemProgress(UUID uuid, Material material) {
try (Connection con = ds.getConnection()) {
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + prefix + "items WHERE player = ? AND item = ?");
ps.setString(1, uuid.toString());
ps.setString(2, material.name());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return rs.getInt("sold");
}
ps = con.prepareStatement("INSERT INTO " + prefix + "items (player, item) VALUES (?, ?)");
ps.setString(1, uuid.toString());
ps.setString(2, material.name());
ps.execute();
return getItemProgress(uuid, material);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return 0;
}
public void progressItem(UUID uuid, Material material) {
try (Connection con = ds.getConnection()) {
PreparedStatement ps = con.prepareStatement("UPDATE " + prefix + "items SET sold = sold+1 WHERE player = ? AND item = ?");
ps.setString(1, uuid.toString());
ps.setString(2, material.name());
ps.execute();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public void progressVillager(UUID uuid) {
try (Connection con = ds.getConnection()) {
PreparedStatement ps = con.prepareStatement("UPDATE " + prefix + "players SET villager_level = villager_level+1 WHERE uuid = ?");
ps.setString(1, uuid.toString());
ps.execute();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}

View File

@ -0,0 +1,23 @@
package ru.redguy.qseller;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class H2Database extends Database{
protected H2Database(HikariDataSource ds) {
super(ds, "");
Database.instance = this;
}
@Override
boolean isTableExists(String name, Connection con) throws SQLException {
PreparedStatement st = con.prepareStatement("SELECT * FROM information_schema.tables WHERE table_name = ?");
st.setString(1, name.toUpperCase());
ResultSet rs = st.executeQuery();
return rs.next();
}
}

View File

@ -0,0 +1,23 @@
package ru.redguy.qseller;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MySQLDatabase extends Database{
protected MySQLDatabase(HikariDataSource ds, String tablePrefix) {
super(ds, tablePrefix);
Database.instance = this;
}
@Override
boolean isTableExists(String name, Connection con) throws SQLException {
PreparedStatement st = con.prepareStatement("SHOW TABLES LIKE ?");
st.setString(1, this.getPrefix() + name);
ResultSet rs = st.executeQuery();
return rs.next();
}
}

View File

@ -0,0 +1,199 @@
package ru.redguy.qseller;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import me.clip.placeholderapi.PlaceholderAPI;
import net.citizensnpcs.api.event.NPCRightClickEvent;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.ipvp.canvas.MenuFunctionListener;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public final class QSeller extends JavaPlugin implements Listener {
static {
ConfigurationSerialization.registerClass(SellItem.class, "SellItem");
}
private static QSeller instance;
public static QSeller getInstance() {
return instance;
}
public Economy econ = null;
@Override
public void onEnable() {
instance = this;
defConf("db.type","h2");
defConf("db._typeComment","h2 or mysql");
defConf("db.h2.file","base.db");
defConf("db.mysql.host","localhost");
defConf("db.mysql.port",3306);
defConf("db.mysql.base","reputation");
defConf("db.mysql.tablePrefix","seller_");
defConf("db.mysql.user","admin");
defConf("db.mysql.pass","StarWarsMonster123");
defConf("db.mysql.useSSL",false);
defConf("db.mysql.maximumPoolSize",1);
defConf("db.mysql.minimumIdle",1);
defConf("db.mysql.serverTimezone","UTC");
defConf("db.mysql.maxLifetimeSeconds",30);
defConf("game.menu.structure",new ArrayList<String>() {{
add("#########");add("#iiiiiii#");add("#iiiiiii#");add("#iiiiiii#");add("#########");add("####b####");
}});
defConf("game.menu.title","Торговец {{level}} ур.");
defConf("game.menu.npcs",new ArrayList<Integer>() {{
add(-1);
}});
defConf("game.menu.items",new ArrayList<SellItem>() {{
add(new SellItem(Material.SUGAR_CANE));add(new SellItem(Material.CARROT_ITEM));
add(new SellItem(Material.POTATO_ITEM));add(new SellItem(Material.MELON_BLOCK));
add(new SellItem(Material.PUMPKIN));add(new SellItem(Material.NETHER_STALK));
add(new SellItem(Material.CACTUS));add(new SellItem(Material.STRING));
}});
defConf("game.menu.startStacks",10);
defConf("game.menu.step",15);
defConf("game.menu.backgroundColor",15);
defConf("game.menu.maxVillagerLevel",100);
defConf("game.menu.item.lore",new ArrayList<String>() {{
add("Нажмите, чтобы продать");
add("Стак за {{price}}");
add("Мин. цена {{min_price}}");
add("Прогресс {{progress_cur}}/{{progress_max}} стаков");
}});
defConf("game.menu.info.tittle","Информация");
defConf("game.menu.info.lore",new ArrayList<String>() {{
add("Торгуй с умом");
}});
defConf("messages.mustBePlayer","Ты должен быть игроком");
defConf("messages.notAnyWhere","Вы не можете открывать торговлю дистанционно");
defConf("messages.noPerm","У вас прав нет на это");
defConf("messages.sold","Вы продали стак и получили {{price}}");
defConf("messages.notEnoughItems","Для продажи нужем минимум стак!");
saveConfig();
if (getServer().getPluginManager().getPlugin("Vault") == null) {
getLogger().warning("Oh shit, vault not found!");
}
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
getLogger().warning("Oh shit, vault economy not found!");
}
econ = rsp.getProvider();
if(this.getString("db.type").equals("mysql")) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://" + getString("db.mysql.host") + ":" + getInt("db.mysql.port") + "/" + getString("db.mysql.base") + "?serverTimezone=" + getString("db.mysql.serverTimezone") + "&allowPublicKeyRetrieval=true&useSSL=" + getBoolean("db.mysql.useSSL"));
config.setUsername(getString("db.mysql.user"));
config.setPassword(getString("db.mysql.pass"));
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("maximumPoolSize", getInt("db.mysql.maximumPoolSize"));
config.addDataSourceProperty("minimumIdle", getInt("db.mysql.minimumIdle"));
config.setMaxLifetime(getInt("db.mysql.maxLifetimeSeconds")*1000L);
new MySQLDatabase(new HikariDataSource(config),this.getString("db.mysql.tablePrefix"));
} else {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:h2:"+new File(getDataFolder(),getString("db.h2.file")).getAbsolutePath());
config.setDriverClassName("org.h2.Driver");
new H2Database(new HikariDataSource(config));
}
Bukkit.getPluginManager().registerEvents(new MenuFunctionListener(), this);
Bukkit.getPluginManager().registerEvents(this,this);
Bukkit.getServer().getPluginCommand("qseller").setExecutor(new QSellerCommand());
Bukkit.getServer().getPluginCommand("qseller").setTabCompleter(new QSellerCommand.TabComplete());
}
@EventHandler
public void onNPCClick(NPCRightClickEvent event) {
if(getConfig().getIntegerList("game.menu.npcs").contains(event.getNPC().getId())) {
new QSellerMenu().open(event.getClicker());
}
}
@Override
public void onDisable() {
Database.getInstance().disconnect();
}
public String getString(String name) {
return getConfig().getString(name);
}
public List<String> getStringList(String name) {
return getConfig().getStringList(name);
}
public List<SellItem> getSellItemList(String name) {
List<?> somethingList = getConfig().getList(name);
if (somethingList == null) {
return new ArrayList<>(0);
}
List<SellItem> result = new ArrayList<>();
for (Object object : somethingList) {
if (object instanceof SellItem) {
result.add((SellItem) object);
}
}
return result;
}
public List<String> getParsedStringList(String name, OfflinePlayer player) {
return getConfig().getStringList(name).stream().map(str -> PlaceholderAPI.setPlaceholders(player, parseInternalPlaceholders(ChatColor.translateAlternateColorCodes('&',str),player))).collect(Collectors.toList());
}
@NotNull
public String getParsedString(String name) {
return ChatColor.translateAlternateColorCodes('&',getConfig().getString(name));
}
@NotNull
public String getParsedString(String name, OfflinePlayer player) {
return PlaceholderAPI.setPlaceholders(player, parseInternalPlaceholders(ChatColor.translateAlternateColorCodes('&',getConfig().getString(name)),player));
}
public String parseInternalPlaceholders(String text, OfflinePlayer player) {
return text.replaceAll("\\{\\{level}}",String.valueOf(Database.getInstance().getVillagerLevel(player.getUniqueId())));
}
public int getInt(String name) {
return getConfig().getInt(name);
}
public boolean getBoolean(String name) {
return getConfig().getBoolean(name);
}
private void defConf(String name, Object value) {
if(!getConfig().isSet(name))
getConfig().set(name, value);
}
}

View File

@ -0,0 +1,55 @@
package ru.redguy.qseller;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import java.util.List;
public class QSellerCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 0: {
if(sender instanceof Player) {
if(sender.hasPermission("qseller.open")) {
new QSellerMenu().open((Player) sender);
} else {
sender.sendMessage(QSeller.getInstance().getParsedString("messages.notAnyWhere"));
}
} else {
sender.sendMessage(QSeller.getInstance().getParsedString("messages.mustBePlayer"));
}
break;
}
case 1: {
if(args[0].equals("reload")) {
if(sender.hasPermission("qseller.reload")) {
QSeller.getInstance().reloadConfig();
} else {
sender.sendMessage(QSeller.getInstance().getParsedString("messages.noPerm"));
}
} else if(Bukkit.getPlayer(args[0])!=null) {
if(sender.hasPermission("qseller.open.others")) {
new QSellerMenu().open(Bukkit.getPlayer(args[0]));
} else {
sender.sendMessage(QSeller.getInstance().getParsedString("messages.noPerm"));
}
}
break;
}
}
return true;
}
public static class TabComplete implements TabCompleter {
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return null;
}
}
}

View File

@ -0,0 +1,171 @@
package ru.redguy.qseller;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import org.ipvp.canvas.ClickInformation;
import org.ipvp.canvas.Menu;
import org.ipvp.canvas.slot.Slot;
import org.ipvp.canvas.type.ChestMenu;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class QSellerMenu {
Menu menu;
/**
* Removes the items of type from an inventory.
* @param inventory Inventory to modify
* @param type The type of Material to remove
* @param amount The amount to remove, or Integer.MAX_VALUE to remove all
* @return The amount of items that could not be removed, 0 for success, or -1 for failures
*/
public static int removeItems(Inventory inventory, Material type, short meta, int amount) {
if(type == null || inventory == null)
return -1;
if (amount <= 0)
return -1;
if (amount == Integer.MAX_VALUE) {
inventory.remove(type);
return 0;
}
HashMap<Integer,ItemStack> retVal = inventory.removeItem(new ItemStack(type,amount,meta));
int notRemoved = 0;
for(ItemStack item: retVal.values()) {
notRemoved+=item.getAmount();
}
return notRemoved;
}
public void sell(Player player, ClickInformation info) {
ItemStack item = info.getClickedSlot().getItem(player);
if(player.getInventory().contains(new ItemStack(item.getType(),item.getType().getMaxStackSize(),item.getData().getData()))) {
Optional<SellItem> items = QSeller.getInstance().getSellItemList("game.menu.items").stream().filter(i -> item.getType().equals(i.getItem())&&i.getMeta()==item.getData().getData()).findFirst();
if(items.isPresent()) {
int startStacks = QSeller.getInstance().getInt("game.menu.startStacks");
int step = QSeller.getInstance().getInt("game.menu.step");
int villagerLevel = Database.getInstance().getVillagerLevel(player.getUniqueId());
SellItem sellItem = items.get();
Database.getInstance().progressItem(player.getUniqueId(), item.getType());
removeItems(player.getInventory(), item.getType(), (short) sellItem.getMeta(), item.getType().getMaxStackSize());
double price = countPrice(player,sellItem,villagerLevel,startStacks, step);
QSeller.getInstance().econ.depositPlayer(player, price);
player.sendMessage(QSeller.getInstance().getParsedString("messages.sold", player).replaceAll("\\{\\{price}}",String.valueOf(price)));
checkForNewLevel(player,villagerLevel,startStacks, step);
render(player);
menu.update(player);
}
} else {
player.sendMessage(QSeller.getInstance().getParsedString("messages.notEnoughItems", player));
}
}
private double countPrice(Player player, SellItem sellItem, int villagerLevel, int startStacks, int step) {
int progress = Database.getInstance().getItemProgress(player.getUniqueId(),sellItem.getItem());
return Math.max(sellItem.getHighPrice()+villagerLevel-1-progress, sellItem.getBasePrice());
}
private void checkForNewLevel(Player player,int villagerLevel, int startStacks, int step) {
if(QSeller.getInstance().getInt("game.menu.maxVillagerLevel")<=villagerLevel) return;
for (SellItem sellItem : QSeller.getInstance().getSellItemList("game.menu.items")) {
int progress = Database.getInstance().getItemProgress(player.getUniqueId(),sellItem.getItem());
int maxProgress = startStacks+(villagerLevel-1)*step;
if(progress<maxProgress) return;
}
Database.getInstance().progressVillager(player.getUniqueId());
Menu oldMenu = menu;
menu = ChestMenu.builder(6)
.title(QSeller.getInstance().getParsedString("game.menu.title", player))
.build();
render(player);
oldMenu.close();
menu.open(player);
}
private void render(Player player) {
int i = 0;
int item = 0;
int villagerLevel = Database.getInstance().getVillagerLevel(player.getUniqueId());
int startStacks = QSeller.getInstance().getInt("game.menu.startStacks");
int step = QSeller.getInstance().getInt("game.menu.step");
List<SellItem> items = QSeller.getInstance().getSellItemList("game.menu.items");
for (char ch : String.join("", QSeller.getInstance().getStringList("game.menu.structure")).toCharArray()) {
Slot slot = menu.getSlot(i);
ItemStack stack;
ItemMeta meta;
switch (ch) {
case '#':
stack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) QSeller.getInstance().getInt("game.menu.backgroundColor"));
meta = stack.getItemMeta();
meta.setLocalizedName(" ");
stack.setItemMeta(meta);
slot.setItem(stack);
break;
case 'b':
stack = new ItemStack(Material.SIGN);
meta = stack.getItemMeta();
meta.setLocalizedName(QSeller.getInstance().getParsedString("game.menu.info.tittle", player));
meta.setLore(QSeller.getInstance().getParsedStringList("game.menu.info.lore", player));
stack.setItemMeta(meta);
slot.setItem(stack);
break;
case 'i':
if (item < items.size()) {
SellItem sellItem = items.get(item);
stack = new ItemStack(sellItem.getItem(),1, (byte) sellItem.getMeta());
if(stack.getType().equals(Material.AIR)) {
item++;
break;
}
meta = stack.getItemMeta();
meta.setLore(
QSeller.getInstance().getParsedStringList("game.menu.item.lore", player).stream()
.map(str -> str.replaceAll("\\{\\{price}}", String.valueOf(countPrice(player,sellItem,villagerLevel,startStacks, step))))
.map(str -> str.replaceAll("\\{\\{min_price}}", String.valueOf(sellItem.getBasePrice()+villagerLevel-1)))
.map(str -> str.replaceAll("\\{\\{progress_cur}}", String.valueOf(Database.getInstance().getItemProgress(player.getUniqueId(),stack.getType()))))
.map(str -> str.replaceAll("\\{\\{progress_max}}", String.valueOf(startStacks+(villagerLevel-1)*step)))
.collect(Collectors.toList())
);
stack.setItemMeta(meta);
slot.setItem(stack);
slot.setClickHandler(this::sell);
} else {
stack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 8);
meta = stack.getItemMeta();
meta.setLocalizedName(" ");
stack.setItemMeta(meta);
slot.setItem(stack);
}
item++;
break;
}
i++;
}
}
public void open(Player player) {
menu = ChestMenu.builder(6)
.title(QSeller.getInstance().getParsedString("game.menu.title", player))
.build();
render(player);
menu.open(player);
}
}

View File

@ -0,0 +1,98 @@
package ru.redguy.qseller;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import java.util.LinkedHashMap;
import java.util.Map;
@SerializableAs("SellItem")
public class SellItem implements Cloneable, ConfigurationSerializable {
Material item = Material.AIR;
short meta = 0;
double basePrice = 0.0;
double highPrice = 0.0;
public SellItem(String item, short meta, double basePrice, double highPrice) {
this.item = Material.valueOf(item);
this.meta = meta;
this.basePrice = basePrice;
this.highPrice = highPrice;
}
public SellItem(Material material, short meta, double basePrice, double highPrice) {
this.item = material;
this.meta = meta;
this.basePrice = basePrice;
this.highPrice = highPrice;
}
public SellItem(Material material) {
this.item = material;
}
public Material getItem() {
return item;
}
public void setItem(Material item) {
this.item = item;
}
public short getMeta() {
return meta;
}
public void setMeta(short meta) {
this.meta = meta;
}
public double getBasePrice() {
return basePrice;
}
public void setBasePrice(double basePrice) {
this.basePrice = basePrice;
}
public double getHighPrice() {
return highPrice;
}
public void setHighPrice(double highPrice) {
this.highPrice = highPrice;
}
public Map<String, Object> serialize() {
LinkedHashMap<String,Object> result = new LinkedHashMap<>();
result.put("item", this.getItem().name());
result.put("meta", this.getMeta());
result.put("basePrice", this.getBasePrice());
result.put("highPrice", this.getHighPrice());
return result;
}
public static SellItem deserialize(Map<String, Object> args) {
Material item = Material.AIR;
short meta = 0;
double basePrice = 0.0D;
double highPrice = 0.0D;
if(args.containsKey("item")) {
item = Material.valueOf(String.valueOf(args.get("item")));
}
if(args.containsKey("meta")) {
meta = Short.parseShort(String.valueOf(args.get("meta")));
}
if(args.containsKey("basePrice")) {
basePrice = Double.parseDouble(String.valueOf(args.get("basePrice")));
}
if(args.containsKey("highPrice")) {
highPrice = Double.parseDouble(String.valueOf(args.get("highPrice")));
}
return new SellItem(item,meta,basePrice,highPrice);
}
}

22
src/main/resources/plugin.yml Executable file
View File

@ -0,0 +1,22 @@
name: QSeller
version: '${version}'
main: ru.redguy.qseller.QSeller
prefix: QSell
authors: [ RedGuy ]
description: Seller plugin
website: https://redguy.ru
commands:
qseller:
description: Открытие меню продавца
depend:
- Vault
permissions:
qseller.open:
default: not op
description: Позволяет открыть меню в любой точке мира
qseller.open.others:
default: not op
description: Позволяет открыть меню в любой точке мира для другого игрока
qseller.reload:
default: not op
description: Позволяет перезагрузить конфиг