9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-19 15:09:19 +00:00

Initial commit

This commit is contained in:
HeroBrineGoat
2021-11-08 17:00:01 -05:00
commit af2189e1b2
41 changed files with 2392 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Project exclude paths
/.gradle/
/build/
/build/classes/java/main/

6
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="16" />
</component>
</project>

7
.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
</component>
</project>

16
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

50
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven4" />
<option name="name" value="maven4" />
<option name="url" value="https://repo.extendedclip.com/content/repositories/placeholderapi/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://papermc.io/repo/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven6" />
<option name="name" value="maven6" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://repo.mattstudios.me/artifactory/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven5" />
<option name="name" value="maven5" />
<option name="url" value="https://repo.leonardobishop.com/releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenLocal" />
<option name="name" value="MavenLocal" />
<option name="url" value="file:/$MAVEN_REPOSITORY$/" />
</remote-repository>
</component>
</project>

10
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" default="true" project-jdk-name="16" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

10
.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

49
build.gradle Normal file
View File

@@ -0,0 +1,49 @@
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '6.1.0'
}
group 'io.github.fisher2911'
version '1.0.0'
repositories {
mavenCentral()
mavenLocal()
maven { url 'https://papermc.io/repo/repository/maven-public/' }
maven { url = 'https://repo.mattstudios.me/artifactory/public/' }
maven { url = 'https://jitpack.io' }
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
maven { url = 'https://repo.leonardobishop.com/releases/' }
maven { url = 'https://jitpack.io' }
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
compileOnly 'io.papermc.paper:paper:1.17.1-R0.1-SNAPSHOT'
compileOnly 'org.jetbrains:annotations:22.0.0'
compileOnly 'net.kyori:adventure-api:4.9.3'
implementation 'net.kyori:adventure-text-minimessage:4.2.0-SNAPSHOT'
implementation 'net.kyori:adventure-platform-bukkit:4.0.0'
implementation 'dev.triumphteam:triumph-gui:3.0.3'
implementation 'me.mattstudios.utils:matt-framework:1.4.6'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
}
test {
useJUnitPlatform()
}
shadowJar {
relocate 'dev.triumphteam.gui', 'io.github.fisher2911.hmccosmetics.gui'
relocate 'me.mattstudios.mf', 'io.github.fisher2911.hmccosmetics.mf'
relocate 'net.kyori.adventure.text.minimessage', 'io.github.fisher2911.hmccosmetics.adventure.minimessage'
relocate 'net.kyori.adventure.platform', 'io.github.fisher2911.hmccosmetics.adventure.platform'
relocate 'org.spongepowered.configurate', 'io.github.fisher2911.hmccosmetics.configurate'
}
shadowJar {
archiveBaseName.set('BackpackCosmetics')
archiveClassifier.set('')
archiveVersion.set('')
}

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

Binary file not shown.

View File

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

185
gradlew vendored Normal 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 Normal 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

2
settings.gradle Normal file
View File

@@ -0,0 +1,2 @@
rootProject.name = 'HMCCosmetics'

View File

@@ -0,0 +1,72 @@
package io.github.fisher2911.hmccosmetics;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.listener.JoinListener;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import me.mattstudios.mf.base.CommandManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
public class HMCCosmetics extends JavaPlugin {
private UserManager userManager;
private MessageHandler messageHandler;
private CosmeticsMenu cosmeticsMenu;
private CommandManager commandManager;
@Override
public void onEnable() {
this.messageHandler = new MessageHandler(this);
this.userManager = new UserManager(this);
this.cosmeticsMenu = new CosmeticsMenu(this);
this.messageHandler.load();
this.cosmeticsMenu.load();
this.registerCommands();
this.registerListeners();
this.userManager.startTeleportTask();
}
@Override
public void onDisable() {
this.messageHandler.close();
this.userManager.cancelTeleportTask();
this.userManager.removeAll();
}
private void registerListeners() {
List.of(new JoinListener(this)).
forEach(listener ->
this.getServer().getPluginManager().registerEvents(listener, this)
);
}
private void registerCommands() {
this.commandManager = new CommandManager(this, true);
this.commandManager.getMessageHandler().register(
"cmd.no.console", player ->
this.messageHandler.sendMessage(
player,
Messages.MUST_BE_PLAYER
)
);
this.commandManager.register(new CosmeticsCommand(this));
}
public MessageHandler getMessageHandler() {
return messageHandler;
}
public UserManager getUserManager() {
return userManager;
}
public CosmeticsMenu getCosmeticsMenu() {
return cosmeticsMenu;
}
}

View File

@@ -0,0 +1,31 @@
package io.github.fisher2911.hmccosmetics.command;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import me.mattstudios.mf.annotations.Command;
import me.mattstudios.mf.annotations.Default;
import me.mattstudios.mf.annotations.Permission;
import me.mattstudios.mf.base.CommandBase;
import org.bukkit.entity.Player;
@Command("cosmetics")
public class CosmeticsCommand extends CommandBase {
private final HMCCosmetics plugin;
private final MessageHandler messageHandler;
private final CosmeticsMenu cosmeticsMenu;
public CosmeticsCommand(final HMCCosmetics plugin) {
this.plugin = plugin;
this.messageHandler = this.plugin.getMessageHandler();
this.cosmeticsMenu = this.plugin.getCosmeticsMenu();
}
@Default
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player) {
this.cosmeticsMenu.openDefault(player);
}
}

View File

@@ -0,0 +1,69 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class GuiSerializer implements TypeSerializer<CosmeticGui> {
private static final HMCCosmetics plugin;
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
public static final GuiSerializer INSTANCE = new GuiSerializer();
private GuiSerializer() {}
private static final String TITLE = "title";
private static final String ROWS = "rows";
private static final String ITEMS = "items";
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path) throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public CosmeticGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE);
final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS);
final ConfigurationNode itemsNode = source.node(ITEMS);
final var childrenMap = source.node(ITEMS).childrenMap();
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
for (final var entry : childrenMap.entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) {
continue;
}
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(
GuiItem.class,
entry.getValue()
);
guiItemMap.put(slot, guiItem);
}
return new CosmeticGui(plugin, titleNode.getString(), rowsNode.getInt(), guiItemMap);
}
@Override
public void serialize(final Type type, @Nullable final CosmeticGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,205 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.LeatherArmorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.SkullBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ItemSerializer implements TypeSerializer<GuiItem> {
public static final ItemSerializer INSTANCE = new ItemSerializer();
private static final String MATERIAL = "material";
private static final String AMOUNT = "amount";
private static final String NAME = "name";
private static final String UNBREAKABLE = "unbreakable";
private static final String GLOWING = "glowing";
private static final String LORE = "lore";
private static final String MODEL_DATA = "model-data";
private static final String ENCHANTS = "enchants";
private static final String ITEM_FLAGS = "item-flags";
private static final String TEXTURE = "texture";
private static final String OWNER = "owner";
private static final String COLOR = "color";
private static final String RED = "red";
private static final String GREEN = "green";
private static final String BLUE = "blue";
private static final String PERMISSION = "permission";
private static final String TYPE = "type";
private static final String OPEN_MENU = "open-menu";
private static final String ID = "id";
private ItemSerializer() {
}
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path) throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public GuiItem deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final ConfigurationNode materialNode = this.nonVirtualNode(source, MATERIAL);
final ConfigurationNode amountNode = source.node(AMOUNT);
final ConfigurationNode nameNode = source.node(NAME);
final ConfigurationNode unbreakableNode = source.node(UNBREAKABLE);
final ConfigurationNode glowingNode = source.node(GLOWING);
final ConfigurationNode loreNode = source.node(LORE);
final ConfigurationNode modelDataNode = source.node(MODEL_DATA);
final ConfigurationNode enchantsNode = source.node(ENCHANTS);
final ConfigurationNode itemFlagsNode = source.node(ITEM_FLAGS);
final ConfigurationNode textureNode = source.node(TEXTURE);
final ConfigurationNode ownerNode = source.node(OWNER);
final ConfigurationNode colorNode = source.node(COLOR);
final ConfigurationNode redNode = colorNode.node(RED);
final ConfigurationNode greenNode = colorNode.node(GREEN);
final ConfigurationNode blueNode = colorNode.node(BLUE);
final ConfigurationNode permissionNode = source.node(PERMISSION);
final ConfigurationNode typeNode = source.node(TYPE);
final ConfigurationNode openMenuNode = source.node(OPEN_MENU);
final ConfigurationNode idNode = source.node(ID);
final Material material = Utils.stringToEnum(Utils.replaceIfNull(materialNode.getString(), ""),
Material.class, Material.AIR);
final int amount = amountNode.getInt();
final String name = StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), ""));
final boolean unbreakable = unbreakableNode.getBoolean();
final boolean glowing = glowingNode.getBoolean();
final List<String> lore = Utils.replaceIfNull(loreNode.getList(String.class), new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
final int modelData = modelDataNode.getInt();
final Set<ItemFlag> itemFlags = Utils.replaceIfNull(itemFlagsNode.getList(String.class), new ArrayList<String>()).
stream().map(flag -> {
try {
return ItemFlag.valueOf(flag.toUpperCase());
} catch (final Exception ignored) {
return null;
}
}).collect(Collectors.toSet());
final String texture = textureNode.getString();
final String owner = ownerNode.getString();
final Color color = Color.fromBGR(redNode.getInt(), greenNode.getInt(), blueNode.getInt());
final Map<Enchantment, Integer> enchantments =
Utils.replaceIfNull(enchantsNode.getList(String.class),
new ArrayList<String>()).
stream().
collect(Collectors.toMap(enchantmentString -> {
if (!enchantmentString.contains(":")) {
return null;
}
final NamespacedKey namespacedKey = NamespacedKey.minecraft(enchantmentString.
split(":")[0].
toLowerCase());
return Registry.ENCHANTMENT.get(namespacedKey);
}, enchantmentString -> {
if (!enchantmentString.contains(":")) {
return 0;
}
try {
return Integer.parseInt(enchantmentString.split(":")[1]);
} catch (final NumberFormatException exception) {
return 0;
}
}));
final ItemBuilder itemBuilder;
if (material == Material.PLAYER_HEAD) {
itemBuilder = SkullBuilder.
create();
if (texture != null) {
((SkullBuilder) itemBuilder).texture(texture);
} else if (owner != null) {
final OfflinePlayer player = Bukkit.getOfflinePlayer(owner);
((SkullBuilder) itemBuilder).owner(player);
}
} else if (LeatherArmorBuilder.isLeatherArmor(material)) {
itemBuilder = LeatherArmorBuilder.from(material);
if (color != null) {
((LeatherArmorBuilder) itemBuilder).color(color);
}
} else {
itemBuilder = ItemBuilder.from(material);
}
final ItemStack itemStack = itemBuilder.
amount(amount).
name(name).
unbreakable(unbreakable).
glow(glowing).
lore(lore).
modelData(modelData).
enchants(enchantments, true).
itemFlags(itemFlags).
build();
try {
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
Utils.replaceIfNull(
typeNode.getString(), ""
).toUpperCase(Locale.ROOT)
);
final String permission = permissionNode.getString();
return new ArmorItem(
itemStack,
Utils.replaceIfNull(idNode.getString(), ""),
permission,
cosmeticType);
} catch (final IllegalArgumentException exception) {
final String openMenu = openMenuNode.getString(
Utils.replaceIfNull(OPEN_MENU, ""));
return dev.triumphteam.gui.builder.item.ItemBuilder.from(
itemStack).
asGuiItem(event -> {
final HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
});
}
}
@Override
public void serialize(final Type type, @Nullable final GuiItem obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,81 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ArmorItem extends GuiItem {
private final String id;
private final String permission;
private final Type type;
public ArmorItem(
@NotNull final ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final String id, final String permission,
final Type type) {
super(itemStack, action);
this.id = id;
this.permission = permission;
this.type = type;
}
public ArmorItem(
@NotNull final ItemStack itemStack,
final String id,
final String permission,
final Type type) {
super(itemStack);
this.id = id;
this.permission = permission;
this.type = type;
}
public ArmorItem(
@NotNull final Material material,
final String id,
final String permission,
final Type type) {
super(material);
this.id = id;
this.permission = permission;
this.type = type;
}
public ArmorItem(
@NotNull final Material material,
@Nullable final GuiAction<InventoryClickEvent> action,
final String id,
final String permission,
final Type type) {
super(material, action);
this.id = id;
this.permission = permission;
this.type = type;
}
public String getId() {
return id;
}
public String getPermission() {
return permission;
}
public Type getType() {
return type;
}
public enum Type {
HAT,
BACKPACK
}
}

View File

@@ -0,0 +1,157 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
public class CosmeticGui {
private final HMCCosmetics plugin;
private final MessageHandler messageHandler;
private final String title;
private final int rows;
private final Map<Integer, GuiItem> guiItemMap;
private Gui gui;
public CosmeticGui(
final HMCCosmetics plugin,
final String title,
final int rows,
final Map<Integer, GuiItem> guiItemMap) {
this.plugin = plugin;
this.messageHandler = this.plugin.getMessageHandler();
this.title = title;
this.rows = rows;
this.guiItemMap = guiItemMap;
}
private void setItems(final User user) {
final Player player = user.getPlayer();
if (player == null) {
return;
}
for (final var entry : guiItemMap.entrySet()) {
final int slot = entry.getKey();
final GuiItem guiItem = entry.getValue();
if (guiItem instanceof final ArmorItem armorItem) {
final Map<String, String> placeholders = new HashMap<>();
final PlayerArmor playerArmor = user.getPlayerArmor();
final ArmorItem hat = playerArmor.getHat();
final ArmorItem backpack = playerArmor.getBackpack();
final ArmorItem.Type type = armorItem.getType();
final String id = switch (type) {
case HAT -> hat.getId();
case BACKPACK -> backpack.getId();
};
placeholders.put(
Placeholder.ENABLED,
String.valueOf(id.equals(armorItem.getId())).
toLowerCase(Locale.ROOT));
placeholders.put(
Placeholder.ALLOWED,
String.valueOf(
player.hasPermission(armorItem.getPermission())).
toUpperCase(Locale.ROOT)
);
this.gui.setItem(slot,
new GuiItem(
ItemBuilder.from(
armorItem.getItemStack()
).namePlaceholders(placeholders).
lorePlaceholders(placeholders).
build(),
event -> {
final String permission = armorItem.getPermission();
if (permission != null &&
!permission.isBlank() &&
!player.hasPermission(armorItem.getPermission())) {
this.messageHandler.sendMessage(
player,
Messages.NO_PERMISSION
);
return;
}
this.setUserArmor(player, user, armorItem);
}
)
);
continue;
}
this.gui.setItem(slot, guiItem);
}
}
private void setUserArmor(
final HumanEntity player,
final User user,
final ArmorItem armorItem) {
if (player == null) {
return;
}
final ArmorItem.Type type = armorItem.getType();
switch (type) {
case HAT -> user.setOrUnsetHat(armorItem);
case BACKPACK -> user.setOrUnsetBackpack(armorItem);
}
}
public void open(final HumanEntity humanEntity) {
final Optional<User> optionalUser = this.plugin.getUserManager().get(humanEntity.getUniqueId());
if (optionalUser.isEmpty()) {
return;
}
final User user = optionalUser.get();
this.gui = Gui.gui().
title(Adventure.MINI_MESSAGE.parse(this.title)).
rows(this.rows).
create();
this.gui.setDefaultClickAction(event -> {
event.setCancelled(true);
this.setItems(user);
this.gui.update();
});
this.setItems(user);
this.gui.open(humanEntity);
}
}

View File

@@ -0,0 +1,89 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.GuiSerializer;
import io.github.fisher2911.hmccosmetics.config.ItemSerializer;
import org.bukkit.entity.HumanEntity;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class CosmeticsMenu {
public static final String MAIN_MENU = "main";
private final HMCCosmetics plugin;
private final Map<String, CosmeticGui> guiMap = new HashMap<>();
public CosmeticsMenu(final HMCCosmetics plugin) {
this.plugin = plugin;
}
public void openMenu(final String id, final HumanEntity humanEntity) {
final CosmeticGui cosmeticGui = this.guiMap.get(id);
if (cosmeticGui != null) {
cosmeticGui.open(humanEntity);
}
}
public void openDefault(final HumanEntity humanEntity) {
this.openMenu(MAIN_MENU, humanEntity);
}
public void load() {
final File file = Path.of(this.plugin.getDataFolder().getPath(),
"menus").toFile();
if (!Path.of(this.plugin.getDataFolder().getPath(),
"menus",
"main").toFile().exists()) {
this.plugin.saveResource(
new File("menus", "main.yml").getPath(),
false
);
}
if (!file.exists() ||
!file.isDirectory()) {
return;
}
final File[] files = file.listFiles();
if (files == null) {
return;
}
for (final File guiFile : files) {
final String id = guiFile.getName().replace(".yml", "");
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
path(Path.of(guiFile.getPath())).
defaultOptions(opts ->
opts.serializers(build -> {
build.register(GuiItem.class, ItemSerializer.INSTANCE);
build.register(CosmeticGui.class, GuiSerializer.INSTANCE);
}))
.build();
try {
final ConfigurationNode source = loader.load();
this.guiMap.put(id, source.get(CosmeticGui.class));
} catch (final ConfigurateException exception) {
exception.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,48 @@
package io.github.fisher2911.hmccosmetics.inventory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class PlayerArmor {
private ArmorItem hat;
private ArmorItem backpack;
public PlayerArmor(final ArmorItem hat, final ArmorItem backpack) {
this.hat = hat;
this.backpack = backpack;
}
public static PlayerArmor empty() {
return new PlayerArmor(
new ArmorItem(
new ItemStack(Material.AIR),
"",
"",
ArmorItem.Type.HAT
),
new ArmorItem(
new ItemStack(Material.AIR),
"",
"",
ArmorItem.Type.BACKPACK
));
}
public ArmorItem getHat() {
return hat;
}
public void setHat(final ArmorItem hat) {
this.hat = hat;
}
public ArmorItem getBackpack() {
return backpack;
}
public void setBackpack(final ArmorItem backpack) {
this.backpack = backpack;
}
}

View File

@@ -0,0 +1,29 @@
package io.github.fisher2911.hmccosmetics.listener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class JoinListener implements Listener {
private final HMCCosmetics plugin;
private final UserManager userManager;
public JoinListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
}
@EventHandler
public void onJoin(final PlayerJoinEvent event) {
this.userManager.add(event.getPlayer());
}
@EventHandler
public void onQuit(final PlayerQuitEvent event) {
this.userManager.remove(event.getPlayer().getUniqueId());
}
}

View File

@@ -0,0 +1,24 @@
package io.github.fisher2911.hmccosmetics.message;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.transformation.TransformationRegistry;
import net.kyori.adventure.text.minimessage.transformation.TransformationType;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class Adventure {
public static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
.hexColors()
.useUnusualXRepeatedCharacterHexFormat()
.build();
public static final MiniMessage MINI_MESSAGE = MiniMessage.builder()
.transformations(TransformationRegistry.
builder().
add(TransformationType.CLICK_EVENT,
TransformationType.DECORATION,
TransformationType.COLOR
).build())
.build();
}

View File

@@ -0,0 +1,8 @@
package io.github.fisher2911.hmccosmetics.message;
public class ErrorMessages {
public static final String INVALID_ITEM = "%s is not a valid %s in file %s";
public static final String ITEM_NOT_FOUND = "%s was not found in file %s";
}

View File

@@ -0,0 +1,57 @@
package io.github.fisher2911.hmccosmetics.message;
import java.util.Objects;
public class Message {
private final String key;
private final String message;
private final Type type;
public Message(final String key, final String message, final Type type) {
this.key = key;
this.message = message;
this.type = type;
}
public Message(final String key, final String message) {
this.message = message;
this.key = key;
this.type = Type.MESSAGE;
}
public String getKey() {
return key;
}
public String getMessage() {
return this.message;
}
public Type getType() {
return type;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Message message = (Message) o;
return Objects.equals(key, message.key);
}
@Override
public int hashCode() {
return Objects.hash(message);
}
public enum Type {
MESSAGE,
ACTION_BAR,
TITLE
}
}

View File

@@ -0,0 +1,158 @@
package io.github.fisher2911.hmccosmetics.message;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.title.Title;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
public class MessageHandler {
private final HMCCosmetics plugin;
private final Logger logger;
private final BukkitAudiences adventure;
private final Map<String, Message> messageMap = new HashMap<>();
public MessageHandler(final HMCCosmetics plugin) {
this.plugin = plugin;
this.logger = this.plugin.getLogger();
this.adventure = BukkitAudiences.create(this.plugin);
}
/**
* Closes adventure
*/
public void close() {
adventure.close();
}
/**
*
* @param sender receiver of message
* @param key message key
* @param placeholders placeholders
*/
public void sendMessage(final CommandSender sender, final Message key, final Map<String, String> placeholders) {
final String message = StringUtils.applyPlaceholders(this.getMessage(key), placeholders);
final Component component = Adventure.MINI_MESSAGE.parse(message);
this.adventure.sender(sender).sendMessage(component);
}
/**
*
* @param sender receiver of message
* @param key message key
*/
public void sendMessage(final CommandSender sender, final Message key) {
this.sendMessage(sender, key, Collections.emptyMap());
}
/**
*
* @param player receiver of message
* @param key message key
* @param placeholders placeholders
*/
public void sendActionBar(final Player player, final Message key, final Map<String, String> placeholders) {
final String message = StringUtils.applyPlaceholders(this.getMessage(key), placeholders);
Component component = Adventure.MINI_MESSAGE.parse(message);
this.adventure.player(player).sendActionBar(component);
}
/**
*
* @param player receiver of message
* @param key message key
*/
public void sendActionBar(final Player player, final Message key) {
this.sendActionBar(player, key, Collections.emptyMap());
}
/**
*
* @param player receiver of message
* @param key message key
* @param placeholders placeholders
*/
public void sendTitle(final Player player, final Message key, final Map<String, String> placeholders) {
final String message = StringUtils.applyPlaceholders(this.getMessage(key), placeholders);
Component component = Adventure.MINI_MESSAGE.parse(message);
this.adventure.player(player).showTitle(Title.title(component, Component.empty()));
}
/**
*
* @param player receiver of message
* @param key message key
*/
public void sendTitle(final Player player, final Message key) {
this.sendTitle(player, key, Collections.emptyMap());
}
/**
*
* @param key message key
* @return message, or empty string if message not found
*/
public String getMessage(final Message key) {
return this.messageMap.getOrDefault(key.getKey(), key).getMessage();
}
/**
* Loads all messages from messages.yml
*/
public void load() {
final String fileName = "messages.yml";
final File file = new File(this.plugin.getDataFolder(), fileName);
if (!file.exists()) {
this.plugin.saveResource(fileName, false);
}
final FileConfiguration config = YamlConfiguration.loadConfiguration(file);
String prefix = config.getString("prefix");
if (prefix == null) {
prefix = "";
}
for (final String key : config.getKeys(false)) {
final String message = Utils.replaceIfNull(config.getString(key), "", value -> {
if (value == null) {
this.logger.warning(String.format(ErrorMessages.ITEM_NOT_FOUND, "message", fileName));
}
}).replace(Placeholder.PREFIX, prefix);
final Message.Type messageType = Utils.stringToEnum(
Utils.replaceIfNull(config.getString("type"), "")
, Message.Type.class, Message.Type.MESSAGE
);
this.messageMap.put(key, new Message(key, message, messageType));
}
}
}

View File

@@ -0,0 +1,17 @@
package io.github.fisher2911.hmccosmetics.message;
public class Messages {
public static final Message NO_PERMISSION =
new Message("no-permission", "You do not have permission for this!");
public static final Message SET_HAT =
new Message("set-hat", "Set hat");
public static final Message REMOVED_HAT =
new Message("removed-hat", "Removed hat");
public static final Message SET_BACKPACK =
new Message("set-backpack", "Set backpack");
public static final Message REMOVED_BACKPACK =
new Message("removed-backpack", "Removed backpack");
public static final Message MUST_BE_PLAYER =
new Message("must-be-player", "You must be a player to do this!");
}

View File

@@ -0,0 +1,7 @@
package io.github.fisher2911.hmccosmetics.message;
public class Permission {
public static final String DEFAULT_COMMAND = "hmccosmetics.cmd.default";
}

View File

@@ -0,0 +1,12 @@
package io.github.fisher2911.hmccosmetics.message;
public class Placeholder {
public static final String PREFIX = "%prefix%";
public static final String TYPE = "%type%";
public static final String ITEM = "%item%";
public static final String FILE = "%file%";
public static final String ENABLED = "%enabled%";
public static final String ALLOWED = "%allowed%";
}

View File

@@ -0,0 +1,124 @@
package io.github.fisher2911.hmccosmetics.user;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class User {
private final UUID uuid;
private final PlayerArmor playerArmor;
private ArmorStand attached;
public User(final UUID uuid, final PlayerArmor playerArmor) {
this.uuid = uuid;
this.playerArmor = playerArmor;
}
public @Nullable Player getPlayer() {
return Bukkit.getPlayer(this.uuid);
}
public UUID getUuid() {
return uuid;
}
public PlayerArmor getPlayerArmor() {
return playerArmor;
}
public void setBackpack(final ArmorItem backpack) {
this.playerArmor.setBackpack(backpack);
}
public void setOrUnsetBackpack(final ArmorItem backpack) {
if (backpack.getId().equals(this.playerArmor.getBackpack().getId())) {
this.setBackpack(new ArmorItem(
new ItemStack(Material.AIR),
"",
"",
ArmorItem.Type.BACKPACK
));
return;
}
this.setBackpack(backpack);
}
public void setHat(final ArmorItem hat) {
this.playerArmor.setHat(hat);
this.getPlayer().getEquipment().setHelmet(this.playerArmor.getHat().getItemStack());
}
public void setOrUnsetHat(final ArmorItem hat) {
if (hat.getId().equals(this.playerArmor.getHat().getId())) {
this.setHat(new ArmorItem(
new ItemStack(Material.AIR),
"",
"",
ArmorItem.Type.HAT
));
return;
}
this.setHat(hat);
}
public void detach() {
if (this.attached != null) {
this.attached.remove();
}
}
// teleports armor stand to the correct position
// todo change to packets
public void updateArmorStand() {
final ArmorItem backpackArmorItem = this.playerArmor.getBackpack();
if (backpackArmorItem == null || backpackArmorItem.getItemStack().getType() == Material.AIR) {
return;
}
final ItemStack backpackItem = backpackArmorItem.getItemStack();
final Player player = this.getPlayer();
if (player == null) {
return;
}
if (this.attached == null) {
this.attached = player.getWorld().spawn(player.getLocation(),
ArmorStand.class,
armorStand -> {
armorStand.setVisible(false);
player.addPassenger(armorStand);
});
}
if (!player.getPassengers().contains(this.attached)) {
player.addPassenger(this.attached);
}
final EntityEquipment equipment = this.attached.getEquipment();
if (!backpackItem.equals(equipment.getChestplate())) {
equipment.setChestplate(backpackItem);
}
this.attached.
setRotation(
player.getLocation().getYaw(),
player.getLocation().getPitch());
}
}

View File

@@ -0,0 +1,67 @@
package io.github.fisher2911.hmccosmetics.user;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class UserManager {
private final HMCCosmetics plugin;
private final Map<UUID, User> userMap = new HashMap<>();
private BukkitTask teleportTask;
public UserManager(final HMCCosmetics plugin) {
this.plugin = plugin;
}
public void add(final Player player) {
final UUID uuid = player.getUniqueId();
this.userMap.put(uuid, new User(uuid, PlayerArmor.empty()));
}
public Optional<User> get(final UUID uuid) {
return Optional.ofNullable(this.userMap.get(uuid));
}
public void remove(final UUID uuid) {
this.get(uuid).ifPresent(User::detach);
this.userMap.remove(uuid);
}
public void startTeleportTask() {
this.teleportTask = Bukkit.getScheduler().runTaskTimer(
this.plugin,
() -> this.userMap.values().forEach(
User::updateArmorStand
),
1,
1
);
}
public void removeAll() {
for (final var user : this.userMap.values()) {
user.detach();
}
this.userMap.clear();
}
public void cancelTeleportTask() {
this.teleportTask.cancel();
}
}

View File

@@ -0,0 +1,38 @@
package io.github.fisher2911.hmccosmetics.util;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import net.kyori.adventure.text.Component;
import java.util.Map;
public class StringUtils {
/**
*
* @param message message being translated
* @param placeholders placeholders applied
* @return message with placeholders applied
*/
public static String applyPlaceholders(String message, final Map<String, String> placeholders) {
for (final Map.Entry<String, String> entry : placeholders.entrySet()) {
message = message.replace(entry.getKey(), entry.getValue());
}
return message;
}
/**
*
* @param parsed message to be parsed
* @return MiniMessage parsed string
*/
public static Component parse(final String parsed) {
return Adventure.MINI_MESSAGE.parse(parsed);
}
public static String parseStringToString(final String parsed) {
return Adventure.SERIALIZER.serialize(Adventure.MINI_MESSAGE.parse(parsed));
}
}

View File

@@ -0,0 +1,105 @@
package io.github.fisher2911.hmccosmetics.util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class Utils {
/**
* @param original Object to be checked if null
* @param replacement Object returned if original is null
* @return original if not null, otherwise replacement
*/
public static <T> T replaceIfNull(final @Nullable T original, final @NotNull T replacement) {
return replaceIfNull(original, replacement, t -> {});
}
/**
*
* @param original Object to be checked if null
* @param replacement Object returned if original is null
* @param consumer accepts the original object, can be used for logging
* @return original if not null, otherwise replacement
*/
public static <T> T replaceIfNull(final @Nullable T original, final T replacement, final @NotNull Consumer<T> consumer) {
if (original == null) {
consumer.accept(replacement);
return replacement;
}
consumer.accept(original);
return original;
}
/**
*
* @param t object being checked
* @param consumer accepted if t is not null
* @param <T> type
*/
public static <T> void doIfNotNull(final @Nullable T t, final @NotNull Consumer<T> consumer) {
if (t == null) {
return;
}
consumer.accept(t);
}
/**
*
* @param t object being checked
* @param function applied if t is not null
* @param <T> type
* @return
*/
public static <T> Optional<T> returnIfNotNull(final @Nullable T t, final @NotNull Function<T, T> function) {
if (t == null) {
return Optional.empty();
}
return Optional.of(function.apply(t));
}
/**
*
* @param enumAsString Enum value as a string to be parsed
* @param enumClass enum type enumAsString is to be converted to
* @param defaultEnum default value to be returned
* @return enumAsString as an enum, or default enum if it could not be parsed
*/
public static <E extends Enum<E>> E stringToEnum(final @NotNull String enumAsString,
final @NotNull Class<E> enumClass,
E defaultEnum) {
return stringToEnum(enumAsString, enumClass, defaultEnum, e -> {});
}
/**
*
* @param enumAsString Enum value as a string to be parsed
* @param enumClass enum type enumAsString is to be converted to
* @param defaultEnum default value to be returned
* @param consumer accepts the returned enum, can be used for logging
* @return enumAsString as an enum, or default enum if it could not be parsed
*/
public static <E extends Enum<E>> E stringToEnum(final @NotNull String enumAsString,
@NotNull final Class<E> enumClass,
final E defaultEnum,
final @NotNull Consumer<E> consumer) {
try {
final E value = Enum.valueOf(enumClass, enumAsString);
consumer.accept(value);
return value;
} catch (final IllegalArgumentException exception) {
consumer.accept(defaultEnum);
return defaultEnum;
}
}
}

View File

@@ -0,0 +1,189 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ItemBuilder {
protected Material material;
protected int amount;
protected ItemMeta itemMeta;
/**
* @param material builder material
*/
ItemBuilder(final Material material) {
this.material = material;
this.itemMeta = Bukkit.getItemFactory().getItemMeta(material);
}
/**
* @param itemStack builder ItemStack
*/
ItemBuilder(final ItemStack itemStack) {
this.material = itemStack.getType();
this.itemMeta = itemStack.hasItemMeta() ? itemStack.getItemMeta() : Bukkit.getItemFactory().getItemMeta(this.material);
}
/**
* @param material builder material
* @return
*/
public static ItemBuilder from(final Material material) {
return new ItemBuilder(material);
}
/**
* @param itemStack builder ItemStack
* @return
*/
public static ItemBuilder from(final ItemStack itemStack) {
return new ItemBuilder(itemStack);
}
/**
* @param amount ItemStack amount
* @return this
*/
public ItemBuilder amount(final int amount) {
this.amount = Math.min(Math.max(1, amount), 64);
return this;
}
/**
* @param name ItemStack name
* @return this
*/
public ItemBuilder name(final String name) {
this.itemMeta.setDisplayName(name);
return this;
}
/**
* Sets placeholders to the item's name
*
* @param placeholders placeholders
*/
public ItemBuilder namePlaceholders(final Map<String, String> placeholders) {
final String name = StringUtils.
applyPlaceholders(this.itemMeta.getDisplayName(), placeholders);
this.itemMeta.displayName(
Adventure.MINI_MESSAGE.parse(
name));
return this;
}
/**
* @param lore ItemStack lore
* @return this
*/
public ItemBuilder lore(final List<String> lore) {
this.itemMeta.setLore(lore);
return this;
}
/**
* Sets placeholders to the item's lore
*
* @param placeholders placeholders
*/
public ItemBuilder lorePlaceholders(final Map<String, String> placeholders) {
final List<String> lore = new ArrayList<>();
final List<String> previousLore = this.itemMeta.getLore();
if (previousLore == null) {
return this;
}
for (final String line : previousLore) {
lore.add(StringUtils.applyPlaceholders(
line, placeholders
));
}
this.itemMeta.setLore(lore);
return this;
}
/**
* @param unbreakable whether the ItemStack is unbreakable
* @return this
*/
public ItemBuilder unbreakable(final boolean unbreakable) {
this.itemMeta.setUnbreakable(unbreakable);
return this;
}
public ItemBuilder glow(final boolean glow) {
if (glow) {
this.itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
this.itemMeta.addEnchant(Enchantment.LUCK, 1, true);
}
return this;
}
/**
* @param enchantments enchants to be added to the ItemStack
* @param ignoreLeveLRestrictions whether to ignore enchantment level restrictions
* @return this
*/
public ItemBuilder enchants(final Map<Enchantment, Integer> enchantments, boolean ignoreLeveLRestrictions) {
enchantments.forEach((enchantment, level) -> this.itemMeta.addEnchant(enchantment, level, ignoreLeveLRestrictions));
return this;
}
/**
* @param itemFlags ItemStack ItemFlags
* @return this
*/
public ItemBuilder itemFlags(final Set<ItemFlag> itemFlags) {
this.itemMeta.addItemFlags(itemFlags.toArray(new ItemFlag[0]));
return this;
}
/**
* @param modelData ItemStack modelData
* @return this
*/
public ItemBuilder modelData(final int modelData) {
this.itemMeta.setCustomModelData(modelData);
return this;
}
/**
* @return built ItemStack
*/
public ItemStack build() {
final ItemStack itemStack = new ItemStack(this.material, Math.max(this.amount, 1));
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@@ -0,0 +1,86 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import java.util.EnumSet;
import java.util.Set;
public class LeatherArmorBuilder extends ItemBuilder{
private static final Set<Material> VALID_ARMOR = EnumSet.of(Material.LEATHER_BOOTS,
Material.LEATHER_LEGGINGS, Material.LEATHER_CHESTPLATE, Material.LEATHER_HELMET);
/**
*
* @param material ItemStack material
*/
LeatherArmorBuilder(final Material material) {
super(material);
}
/**
*
* @param itemStack ItemStack
*/
LeatherArmorBuilder(final ItemStack itemStack) {
super(itemStack);
}
/**
*
* @param material ItemStack material
* @return this
* @throws IllegalArgumentException thrown if material is not leather armor
*/
public static LeatherArmorBuilder from(final Material material) throws IllegalArgumentException {
if (!VALID_ARMOR.contains(material)) {
throw new IllegalArgumentException(material.name() + " is not leather armor!");
}
return new LeatherArmorBuilder(material);
}
/**
*
* @param itemStack ItemStack
* @return this
* @throws IllegalArgumentException thrown if itemStack's type is not leather armor
*/
public static LeatherArmorBuilder from(final ItemStack itemStack) throws IllegalArgumentException {
final Material material = itemStack.getType();
if (!VALID_ARMOR.contains(material)) {
throw new IllegalArgumentException(material.name() + " is not leather armor!");
}
return new LeatherArmorBuilder(itemStack);
}
/**
*
* @param color armor color
* @return this
*/
public LeatherArmorBuilder color(final Color color) {
if (itemMeta instanceof final LeatherArmorMeta meta) {
meta.setColor(color);
this.itemMeta = meta;
}
return this;
}
/**
*
* @param material checked material
* @return true if is leather armor, else false
*/
public static boolean isLeatherArmor(final Material material) {
return VALID_ARMOR.contains(material);
}
}

View File

@@ -0,0 +1,95 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.UUID;
/**
* Some parts taken from https://github.com/TriumphTeam/triumph-gui/blob/master/core/src/main/java/dev/triumphteam/gui/builder/item/SkullBuilder.java
*/
public class SkullBuilder extends ItemBuilder {
private static final Field PROFILE_FIELD;
static {
Field field;
try {
final SkullMeta skullMeta = (SkullMeta) new ItemStack(Material.PLAYER_HEAD).getItemMeta();
field = skullMeta.getClass().getDeclaredField("profile");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
field = null;
}
PROFILE_FIELD = field;
}
/**
*
* @param material The material
*/
SkullBuilder(final Material material) {
super(material);
}
/**
* Creates a new SkullBuilder instance
* @return this
*/
public static SkullBuilder create() {
return new SkullBuilder(Material.PLAYER_HEAD);
}
/**
*
* @param player skull owner
* @return this
*/
public SkullBuilder owner(final OfflinePlayer player) {
if (this.itemMeta instanceof final SkullMeta skullMeta) {
skullMeta.setOwningPlayer(player);
this.itemMeta = skullMeta;
}
return this;
}
/**
*
* @param texture skull texture
* @return this
*/
public SkullBuilder texture(@NotNull final String texture) {
if (PROFILE_FIELD == null) {
return this;
}
final SkullMeta skullMeta = (SkullMeta) this.itemMeta;
final GameProfile profile = new GameProfile(UUID.randomUUID(), null);
profile.getProperties().put("textures", new Property("textures", texture));
try {
PROFILE_FIELD.set(skullMeta, profile);
} catch (IllegalArgumentException | IllegalAccessException ex) {
ex.printStackTrace();
}
this.itemMeta = skullMeta;
return this;
}
}

View File

@@ -0,0 +1,47 @@
title: "<red>Main</red>"
rows: 3
items:
10:
material: NETHERITE_CHESTPLATE
name: "<blue>Backpack"
lore:
- ""
- "Enabled: %enabled%"
- "Allowed: %allowed%"
amount: 1
type: BACKPACK
permission: ""
id: netherite_backpack
11:
material: NETHERITE_HELMET
name: "<blue>Hat"
lore:
- ""
- "Enabled: %enabled%"
- "Allowed: %allowed%"
amount: 1
type: HAT
permission: ""
id: netherite_hat
12:
material: DIAMOND_CHESTPLATE
name: "<blue>Backpack"
lore:
- ""
- "Enabled: %enabled%"
- "Allowed: %allowed%"
amount: 1
type: BACKPACK
permission: ""
id: diamond_backpack
13:
material: DIAMOND_HELMET
name: "<blue>Hat "
lore:
- ""
- "Enabled: %enabled%"
- "Allowed: %allowed%"
amount: 1
type: HAT
permission: ""
id: diamond_hat

View File

@@ -0,0 +1,6 @@
no-permission: "<red>No Permission!"
set-hat: "<green>Set Hat!"
removed-hat: "<green>Removed Hat"
set-backpack: "<green>Set Backpack!"
removed-backpack: "<green>Removed Backpack"
must-be-player: "You must be a player to do this!"

View File

@@ -0,0 +1,8 @@
name: HMCCosmetics
main: io.github.fisher2911.hmccosmetics.HMCCosmetics
version: 1.0.0
api-version: 1.17
permissions:
hmccosmetics.cmd.default:
default: op
description: Permission to execute the default command