diff --git a/.gradle/8.5/checksums/checksums.lock b/.gradle/8.5/checksums/checksums.lock index d435398..2c1b8cc 100644 Binary files a/.gradle/8.5/checksums/checksums.lock and b/.gradle/8.5/checksums/checksums.lock differ diff --git a/.gradle/8.5/checksums/md5-checksums.bin b/.gradle/8.5/checksums/md5-checksums.bin index 1327cc1..98a8e56 100644 Binary files a/.gradle/8.5/checksums/md5-checksums.bin and b/.gradle/8.5/checksums/md5-checksums.bin differ diff --git a/.gradle/8.5/checksums/sha1-checksums.bin b/.gradle/8.5/checksums/sha1-checksums.bin index 64ead5c..0daf1fd 100644 Binary files a/.gradle/8.5/checksums/sha1-checksums.bin and b/.gradle/8.5/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.5/executionHistory/executionHistory.bin b/.gradle/8.5/executionHistory/executionHistory.bin index c7e119f..bd8ff06 100644 Binary files a/.gradle/8.5/executionHistory/executionHistory.bin and b/.gradle/8.5/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.5/executionHistory/executionHistory.lock b/.gradle/8.5/executionHistory/executionHistory.lock index 4d01cad..b275fcc 100644 Binary files a/.gradle/8.5/executionHistory/executionHistory.lock and b/.gradle/8.5/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.5/fileHashes/fileHashes.bin b/.gradle/8.5/fileHashes/fileHashes.bin index 90adcf0..61e328f 100644 Binary files a/.gradle/8.5/fileHashes/fileHashes.bin and b/.gradle/8.5/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.5/fileHashes/fileHashes.lock b/.gradle/8.5/fileHashes/fileHashes.lock index 37407a2..6ab458c 100644 Binary files a/.gradle/8.5/fileHashes/fileHashes.lock and b/.gradle/8.5/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.5/fileHashes/resourceHashesCache.bin b/.gradle/8.5/fileHashes/resourceHashesCache.bin index 5db5d1b..abff864 100644 Binary files a/.gradle/8.5/fileHashes/resourceHashesCache.bin and b/.gradle/8.5/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 29c9dce..b7d6ac4 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin index 4404307..a1bfebd 100644 Binary files a/.gradle/buildOutputCleanup/outputFiles.bin and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe index c39cd17..a511867 100644 Binary files a/.gradle/file-system.probe and b/.gradle/file-system.probe differ diff --git a/.idea/modules.xml b/.idea/modules.xml index 7377310..777feb1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,9 @@ - + + + diff --git a/.idea/modules/Sentinel.main.iml b/.idea/modules/Sentinel.main.iml index bbeeb3e..746f1fd 100644 --- a/.idea/modules/Sentinel.main.iml +++ b/.idea/modules/Sentinel.main.iml @@ -11,4 +11,8 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 04dbda4..e61ae50 100644 --- a/build.gradle +++ b/build.gradle @@ -3,18 +3,20 @@ import java.nio.file.Paths plugins { id 'java' - id("com.github.johnrengelman.shadow") version "8.1.1" + id 'com.gradleup.shadow' version '9.0.0-beta10' } group = project.group version = project.version -jar { - from { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - configurations.runtimeClasspath.collect { - it.isDirectory() ? it : zipTree(it) - } +def targetJavaVersion = 21 +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) } } @@ -36,76 +38,91 @@ repositories { url = 'https://oss.sonatype.org/content/groups/public/' } maven { - url = uri("https://repo.codemc.io/repository/maven-releases/") - } - maven { - url = uri("https://repo.codemc.io/repository/maven-snapshots/") + name = "CodeMC" + url = uri("https://repo.codemc.io/repository/maven-public/") } } dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.11.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.11.0") compileOnly "io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT" implementation 'com.google.code.gson:gson:2.10.1' implementation 'org.ow2.asm:asm-commons:9.5' implementation files("deps/PDK-1.4.0.jar") implementation "com.github.retrooper:packetevents-spigot:2.7.0" + implementation("de.tr7zw:item-nbt-api:2.14.1") } -def targetJavaVersion = 21 -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - sourceCompatibility = javaVersion - targetCompatibility = javaVersion - toolchain.languageVersion.set(JavaLanguageVersion.of(21)) - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } -} - -tasks.withType(JavaCompile).configureEach { - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - options.release = targetJavaVersion - } -} - -tasks.register('copyDeps', Copy) { - from configurations.runtimeClasspath - into 'build/deps' - include '*.jar' -} - - processResources { - def props = [version: version] - inputs.properties props - filteringCharset 'UTF-8' filesMatching('plugin.yml') { - expand props + expand(version: project.version) } } -compileJava.options.encoding("UTF-8") +task cleanPluginYml { + doLast { + def jarFile = shadowJar.archiveFile.get().asFile + def tempDir = file("$buildDir/tmpCleanJar") + tempDir.mkdirs() -tasks.withType(JavaCompile) { - options.encoding = "UTF-8" + // Unpack the jar into a temporary directory + copy { + from zipTree(jarFile) + into tempDir + } + + // Delete any plugin.yml files from anywhere in the unpacked directory + fileTree(tempDir).matching { + include '**/plugin.yml' + }.each { file -> + file.delete() + } + + // Repackage the jar without the plugin.yml files + ant.zip(destfile: jarFile, basedir: tempDir) + delete tempDir + } } -tasks.shadowJar { +task injectPluginYml { + doLast { + def jarFile = shadowJar.archiveFile.get().asFile + def tempDir = file("$buildDir/tmpJar") + tempDir.mkdirs() + + // Unpack the jar that has been cleaned + copy { + from zipTree(jarFile) + into tempDir + } + + // Copy the already filtered plugin.yml from processed resources + copy { + from file("$buildDir/resources/main/plugin.yml") + into tempDir + } + + // Repackage the jar with the updated contents + ant.zip(destfile: jarFile, basedir: tempDir) + delete tempDir + } +} + +shadowJar { + archiveClassifier.set('') + minimize() + + mergeServiceFiles() + + exclude 'plugin.yml' + relocate("com.github.retrooper.packetevents", "me.trouper.sentinel.packetevents.api") relocate("io.github.retrooper.packetevents", "me.trouper.sentinel.packetevents.impl") + relocate("de.tr7zw.changeme.nbtapi", "me.trouper.sentinel.nbtapi.api") + } -task obfuscate(type: JavaExec) { - // Specify the main class in the obfuscator JAR (if required) - - // Path to the obfuscator JAR - classpath = files('obf/grunt-main.jar') - - // Arguments to pass to the obfuscator (e.g., input and output directories) - args = [ - '--config', '.\\obf\\config.json' - ] -} task copyLibs { doLast { @@ -143,6 +160,33 @@ task copyLibs { } } +task obfuscate(type: JavaExec) { + // Path to the obfuscator JAR + classpath = files('obf/grunt-main.jar') + + // Arguments to pass to the obfuscator (e.g., input and output directories) + args = [ + '--config', '.\\obf\\config.json' + ] +} + +tasks.withType(JavaCompile).configureEach { + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release = targetJavaVersion + } +} + +compileJava.options.encoding("UTF-8") + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + test { useJUnitPlatform() +} + +build { + dependsOn(shadowJar) + dependsOn injectPluginYml } \ No newline at end of file diff --git a/build/classes/java/main/me/trouper/sentinel/Sentinel.class b/build/classes/java/main/me/trouper/sentinel/Sentinel.class index 3c6e291..874a300 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/Sentinel.class and b/build/classes/java/main/me/trouper/sentinel/Sentinel.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/Emojis.class b/build/classes/java/main/me/trouper/sentinel/data/Emojis.class deleted file mode 100644 index 5b5129d..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/Emojis.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/WhitelistStorage.class b/build/classes/java/main/me/trouper/sentinel/data/WhitelistStorage.class deleted file mode 100644 index d72fab4..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/WhitelistStorage.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/AdvancedConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/AdvancedConfig.class index eed028c..3519414 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/AdvancedConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/AdvancedConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/FPConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/FPConfig.class index e6cc7f2..cfeb15e 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/FPConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/FPConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig$Plugin.class b/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig$Plugin.class index 8da10d1..ad20e3c 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig$Plugin.class and b/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig$Plugin.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig.class index 2596005..16fe24e 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/MainConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/NBTConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/NBTConfig.class index f9c5cfd..a6c710f 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/NBTConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/NBTConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/StrictConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/StrictConfig.class index fc1f0f2..3803572 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/StrictConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/StrictConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/SwearsConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/SwearsConfig.class index 26f2de3..5dae5ef 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/SwearsConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/SwearsConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockEdit.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockEdit.class index 51427e1..b74f19a 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockEdit.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockEdit.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockExecute.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockExecute.class deleted file mode 100644 index 883e1dd..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockExecute.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartPlace.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartPlace.class index 7342f6a..0c1d6d2 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartPlace.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartPlace.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartUse.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartUse.class index 0df988d..0483e71 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartUse.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockMinecartUse.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockPlace.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockPlace.class index 9157937..a3c034b 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockPlace.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockPlace.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockUse.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockUse.class index cdfdc77..dcaed8c 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockUse.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandBlockUse.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Dangerous.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Dangerous.class index 07d2780..06d3eac 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Dangerous.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Dangerous.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Logged.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Logged.class index 172f4cf..ad430f7 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Logged.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Logged.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Specific.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Specific.class index 4d029f6..3651003 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Specific.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute$Specific.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute.class index 93a8453..feb553d 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CommandExecute.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CreativeHotbarAction.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CreativeHotbarAction.class index ac27fe8..8a24f38 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CreativeHotbarAction.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig$CreativeHotbarAction.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig.class b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig.class index 927e0f4..76b1f60 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig.class and b/build/classes/java/main/me/trouper/sentinel/data/config/ViolationConfig.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/config/lang/LanguageFile.class b/build/classes/java/main/me/trouper/sentinel/data/config/lang/LanguageFile.class index 634ef00..d06244a 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/data/config/lang/LanguageFile.class and b/build/classes/java/main/me/trouper/sentinel/data/config/lang/LanguageFile.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/types/CMDBlockType.class b/build/classes/java/main/me/trouper/sentinel/data/types/CMDBlockType.class deleted file mode 100644 index 30f9f83..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/types/CMDBlockType.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/types/Location.class b/build/classes/java/main/me/trouper/sentinel/data/types/Location.class deleted file mode 100644 index 4ec9547..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/types/Location.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/data/types/WhitelistedBlock.class b/build/classes/java/main/me/trouper/sentinel/data/types/WhitelistedBlock.class deleted file mode 100644 index 12d1d24..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/data/types/WhitelistedBlock.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/CallbackCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/CallbackCommand.class index f599c1c..73c341a 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/CallbackCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/CallbackCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/MessageCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/MessageCommand.class index e1bacc4..503aa73 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/MessageCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/MessageCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/ReopCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/ReopCommand.class index 6b390f6..34b97f8 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/ReopCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/ReopCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/ReplyCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/ReplyCommand.class index 7e969b9..b234058 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/ReplyCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/ReplyCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/SentinelCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/SentinelCommand.class index 1fee522..9977091 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/SentinelCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/SentinelCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/commands/TrapCommand.class b/build/classes/java/main/me/trouper/sentinel/server/commands/TrapCommand.class index 8ea7d50..fb615f5 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/commands/TrapCommand.class and b/build/classes/java/main/me/trouper/sentinel/server/commands/TrapCommand.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/events/ChatEvent.class b/build/classes/java/main/me/trouper/sentinel/server/events/ChatEvent.class deleted file mode 100644 index d9fbde0..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/events/ChatEvent.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.class b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.class index 591af60..ba709da 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.class and b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.class b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.class index 9c33274..b6a0c42 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.class and b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.class b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.class index fdccff9..2265bb8 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.class and b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.class b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.class index 2e08c6f..6d6a3cf 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.class and b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.class b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.class index 3dc6682..ed2f840 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.class and b/build/classes/java/main/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/ConfigGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/ConfigGUI.class deleted file mode 100644 index 1e69919..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/ConfigGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/Items.class b/build/classes/java/main/me/trouper/sentinel/server/gui/Items.class index f823183..35cbc01 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/Items.class and b/build/classes/java/main/me/trouper/sentinel/server/gui/Items.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/MainGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/MainGUI.class index afd9141..250d33d 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/MainGUI.class and b/build/classes/java/main/me/trouper/sentinel/server/gui/MainGUI.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/AntiNukeGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/AntiNukeGUI.class index 02f92d6..a75f013 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/AntiNukeGUI.class and b/build/classes/java/main/me/trouper/sentinel/server/gui/config/AntiNukeGUI.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/ChatGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/ChatGUI.class deleted file mode 100644 index 7b82353..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/ChatGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.class index d970d7d..49a7d25 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.class and b/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.class index e3f79b4..3cb9ef2 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.class and b/build/classes/java/main/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.class deleted file mode 100644 index 84212a7..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.class deleted file mode 100644 index 5236fa2..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.class deleted file mode 100644 index 22435ab..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.class deleted file mode 100644 index d39fc31..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.class deleted file mode 100644 index e6c60e7..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.class deleted file mode 100644 index 22ce165..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.class deleted file mode 100644 index f53df53..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.class deleted file mode 100644 index c796e84..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.class deleted file mode 100644 index 3fe52bb..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.class deleted file mode 100644 index e14f58c..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.class b/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.class deleted file mode 100644 index fc827ca..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/startup/Auth$1.class b/build/classes/java/main/me/trouper/sentinel/startup/Auth$1.class deleted file mode 100644 index 4d97609..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/startup/Auth$1.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/startup/Auth.class b/build/classes/java/main/me/trouper/sentinel/startup/Auth.class deleted file mode 100644 index 5cc5abc..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/startup/Auth.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/startup/Load.class b/build/classes/java/main/me/trouper/sentinel/startup/Load.class deleted file mode 100644 index 3ec683e..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/startup/Load.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/startup/Telemetry.class b/build/classes/java/main/me/trouper/sentinel/startup/Telemetry.class index 5541fb6..03ebba8 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/startup/Telemetry.class and b/build/classes/java/main/me/trouper/sentinel/startup/Telemetry.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/CipherUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/CipherUtils.class deleted file mode 100644 index a117bbb..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/CipherUtils.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/FileUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/FileUtils.class index ca347fe..6f395c1 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/FileUtils.class and b/build/classes/java/main/me/trouper/sentinel/utils/FileUtils.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/ItemUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/ItemUtils.class deleted file mode 100644 index 25e9249..0000000 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/ItemUtils.class and /dev/null differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/MathUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/MathUtils.class index ced59e0..f924456 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/MathUtils.class and b/build/classes/java/main/me/trouper/sentinel/utils/MathUtils.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/PlayerUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/PlayerUtils.class index 0286292..4074108 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/PlayerUtils.class and b/build/classes/java/main/me/trouper/sentinel/utils/PlayerUtils.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/ServerUtils.class b/build/classes/java/main/me/trouper/sentinel/utils/ServerUtils.class index 5b5c16b..115e153 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/ServerUtils.class and b/build/classes/java/main/me/trouper/sentinel/utils/ServerUtils.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/Text.class b/build/classes/java/main/me/trouper/sentinel/utils/Text.class index 548d9f1..4bde813 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/Text.class and b/build/classes/java/main/me/trouper/sentinel/utils/Text.class differ diff --git a/build/classes/java/main/me/trouper/sentinel/utils/trees/EmbedFormatter.class b/build/classes/java/main/me/trouper/sentinel/utils/trees/EmbedFormatter.class index e81db28..bc870e4 100644 Binary files a/build/classes/java/main/me/trouper/sentinel/utils/trees/EmbedFormatter.class and b/build/classes/java/main/me/trouper/sentinel/utils/trees/EmbedFormatter.class differ diff --git a/build/resources/main/plugin.yml b/build/resources/main/plugin.yml index fc2faf1..5612acc 100644 --- a/build/resources/main/plugin.yml +++ b/build/resources/main/plugin.yml @@ -1,5 +1,5 @@ name: SentinelAntiNuke -version: '0.3.0' +version: '0.3.1' main: me.trouper.sentinel.Sentinel api-version: 1.21 authors: [ TheTrouper ] @@ -12,27 +12,20 @@ softdepend: - ViaBackwards - ViaRewind - Geyser-Spigot -load: STARTUP +load: POSTWORLD permissions: sentinel.admin: description: Allows access to all Sentinel admin commands. default: op children: - sentinel.reload: true - sentinel.config: true sentinel.debug: true + sentinel.extras: true sentinel.staff: description: Allows access to Sentinel staff commands. - default: false + default: op children: sentinel.socialspy: true sentinel.false-positive: true - sentinel.reload: - description: Allows the user to reload the Sentinel plugin. - default: false - sentinel.config: - description: Allows the user to modify the Sentinel configuration. - default: false sentinel.false-positive: description: Allows the user to manage false positives. default: false @@ -47,7 +40,10 @@ permissions: default: false sentinel.debug: description: Allows the user to toggle debug mode. - default: false + default: op + sentinel.extras: + description: Sentinel Extra Features + default: op sentinel.commandblock: description: Allows the user to manage command blocks. default: false @@ -130,6 +126,11 @@ commands: usage: /sentinel permission: sentinel.staff permission-message: You do not have permission to use this command. + sentinelextras: + usage: /sentinelextras [alfa|bravo|charlie|delta|echo|foxtrot|golf|hotel|india|juliett] + description: Extra features for sentinel. + permission: sentinel.extra + permission-message: You do not have permission to use this command. sentinelcallback: description: Callback command for Sentinel. usage: /callback diff --git a/build/tmp/.cache/expanded/expanded.lock b/build/tmp/.cache/expanded/expanded.lock index ea05fba..e1cd2a9 100644 Binary files a/build/tmp/.cache/expanded/expanded.lock and b/build/tmp/.cache/expanded/expanded.lock differ diff --git a/build/tmp/compileJava/previous-compilation-data.bin b/build/tmp/compileJava/previous-compilation-data.bin index a89e01c..c447dbe 100644 Binary files a/build/tmp/compileJava/previous-compilation-data.bin and b/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/gradle.properties b/gradle.properties index fbafe19..d996e6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Plugin group = 'me.trouper' -version = 0.3.0 +version = 0.3.1 # Minecraft mc_version = 1.21 diff --git a/obf/config.json b/obf/config.json index 9c42555..c51bbe7 100644 --- a/obf/config.json +++ b/obf/config.json @@ -1,7 +1,7 @@ { "Settings": { - "Input": "./build/libs/Sentinel-0.3.0.jar", - "Output": "./build/libs/Sentinel-0.3.0-obf.jar", + "Input": "./build/libs/Sentinel-0.3.1.jar", + "Output": "./build/libs/Sentinel-0.3.1-obf.jar", "Libraries": [ "./deps" ], @@ -9,6 +9,8 @@ "com/", "io/", "me/trouper/sentinel/data/", + "me/trouper/sentinel/packetevents/", + "me/trouper/sentinel/nbtapi/", "org/", "net/", "module-info" diff --git a/src/main/java/me/trouper/sentinel/Director.java b/src/main/java/me/trouper/sentinel/Director.java new file mode 100644 index 0000000..85194eb --- /dev/null +++ b/src/main/java/me/trouper/sentinel/Director.java @@ -0,0 +1,58 @@ +package me.trouper.sentinel; + +import me.trouper.sentinel.data.IO; +import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager; +import me.trouper.sentinel.server.functions.helpers.MessageHandler; +import me.trouper.sentinel.server.functions.helpers.ReportHandler; +import me.trouper.sentinel.startup.*; +import me.trouper.sentinel.startup.drm.Auth; +import me.trouper.sentinel.startup.drm.Loader; +import me.trouper.sentinel.utils.ServerUtils; + +public final class Director { + + public Loader loader; + public BackdoorDetection backdoorDetection; + public Auth auth; + public Telemetry telemetry; + public Injection injection; + public CBWhitelistManager whitelistManager; + public MessageHandler messageHandler; + public ReportHandler reportHandler; + public IO io; + + public Director() { + Sentinel.getInstance().getLogger().info("Instantiating Systems"); + telemetry = new Telemetry(); + auth = new Auth(); + loader = new Loader(); + backdoorDetection = new BackdoorDetection(); + injection = new Injection(); + whitelistManager = new CBWhitelistManager(); + messageHandler = new MessageHandler(); + reportHandler = new ReportHandler(); + io = new IO(); + } + + public void launch() { + Sentinel.getInstance().getLogger().info("Launching Sentinel"); + Sentinel.getInstance().ip = ServerUtils.getPublicIPAddress(); + Sentinel.getInstance().port = ServerUtils.getPort(); + Sentinel.getInstance().nonce = auth.getNonce(); + + Sentinel.getInstance().getLogger().info("Getting plugin file"); + + Sentinel.getInstance().getLogger().info("Reading Persistent files..."); + + io.loadConfig(); + + Sentinel.getInstance().getLogger().info("Language Status: (%s)".formatted(io.lang.brokenLang)); + + Sentinel.getInstance().getLogger().info("Initializing Auth Identifier"); + + Sentinel.getInstance().license = auth.getLicenseKey(); + Sentinel.getInstance().identifier = auth.getServerID(); + + loader.load(Sentinel.getInstance().license,Sentinel.getInstance().identifier, true); + } +} diff --git a/src/main/java/me/trouper/sentinel/Sentinel.java b/src/main/java/me/trouper/sentinel/Sentinel.java index c13d1cc..652b774 100644 --- a/src/main/java/me/trouper/sentinel/Sentinel.java +++ b/src/main/java/me/trouper/sentinel/Sentinel.java @@ -1,128 +1,116 @@ package me.trouper.sentinel; import com.github.retrooper.packetevents.PacketEvents; +import de.tr7zw.changeme.nbtapi.NBT; import io.github.itzispyder.pdk.PDK; -import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import me.trouper.sentinel.data.WhitelistStorage; -import me.trouper.sentinel.data.config.*; -import me.trouper.sentinel.data.config.lang.LanguageFile; -import me.trouper.sentinel.server.events.PluginCloakingPacket; -import me.trouper.sentinel.startup.Auth; -import me.trouper.sentinel.startup.IndirectLaunch; +import me.trouper.sentinel.server.events.extras.ShadowRealmEvents; +import me.trouper.sentinel.server.events.violations.players.PluginCloakingPacket; import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; -import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.List; public final class Sentinel extends JavaPlugin { - - public static final Logger log = Bukkit.getLogger(); + private static Sentinel instance; - public static LanguageFile lang; - public static File us; - - private static final File dataFolder = new File("plugins/SentinelAntiNuke"); - private static final File violationcfg = new File(Sentinel .dataFolder(),"/violation-config.json"); - private static final File cfgfile = new File(Sentinel.dataFolder(),"/main-config.json"); - private static final File nbtcfg = new File(Sentinel.dataFolder(), "/nbt-config.json"); - private static final File strctcfg = new File(Sentinel.dataFolder(), "/strict.json"); - private static final File swrcfg = new File(Sentinel.dataFolder(), "/swears.json"); - private static final File fpcfg = new File(Sentinel.dataFolder(), "/false-positives.json"); - private static final File advcfg = new File(Sentinel.dataFolder(), "/advanced-config.json"); - private static final File cmdWhitelist = new File(Sentinel.dataFolder(), "/storage/whitelist.json"); - - public static ViolationConfig violationConfig = JsonSerializable.load(violationcfg, ViolationConfig.class, new ViolationConfig()); - public static WhitelistStorage whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage()); - public static MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig()); - public static FPConfig fpConfig = JsonSerializable.load(fpcfg, FPConfig.class, new FPConfig()); - public static SwearsConfig swearConfig = JsonSerializable.load(swrcfg, SwearsConfig.class, new SwearsConfig()); - public static StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig()); - public static NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig()); - public static AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig()); - + private Director director; + public String identifier; public String license; public String nonce; public String ip; public int port; + + /* ]=- Sentinel Startup Flow -=[ + Make sure everything is done in sequence to avoid NullPointerException! + 1. onLoad + - PacketEvents Loading & Registration + 2. onEnable + - Init PacketEvents + - Init NBT-API + - Init PDK + - Instantiate Sentinel + - Instantiate Director + 3. Launch + - Init DRM + - Read Config + 4. Load + - Run DRM Checks + - Register Commands + - Register Events + - Register Timers + */ @Override public void onLoad() { - Sentinel.log.info("\n]======------ Pre-load started ------======["); + getLogger().info("\n]======------ Pre-load started ------======["); - Sentinel.log.info("Setting PacketEvents API"); + getLogger().info("Setting PacketEvents API"); PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); - Sentinel.log.info("Loading PacketEvents"); + getLogger().info("Loading PacketEvents"); PacketEvents.getAPI().load(); - Sentinel.log.info("Registering PacketEvents"); + getLogger().info("Registering PacketEvents"); PacketEvents.getAPI().getEventManager().registerListener(new PluginCloakingPacket()); + PacketEvents.getAPI().getEventManager().registerListener(new ShadowRealmEvents()); } - + @Override - public void onEnable() { - log.info("\n]======------ Loading Sentinel ------======["); + public void onEnable() { + getLogger().info("\n]======------ Loading Sentinel ------======["); - log.info("Initializing PacketEvents"); + getLogger().info("Initializing PacketEvents"); PacketEvents.getAPI().init(); - log.info("Initializing PDK"); + getLogger().info("Pre-loading NBT-API"); + if (!NBT.preloadApi()) { + getLogger().warning("NBT-API wasn't initialized properly. Sentinel may error out."); + } + + getLogger().info("Initializing PDK"); PDK.init(this); - log.info("Instantiating plugin"); + getLogger().info("Instantiating Sentinel"); instance = this; - us = getFile(); - IndirectLaunch.launch(); - } + Sentinel.getInstance().getLogger().info("Instantiating Director"); + director = new Director(); - public void loadConfig() { - // Init - mainConfig = JsonSerializable.load(cfgfile,MainConfig.class,new MainConfig()); - advConfig = JsonSerializable.load(advcfg,AdvancedConfig.class,new AdvancedConfig()); - fpConfig = JsonSerializable.load(fpcfg,FPConfig.class,new FPConfig()); - strictConfig = JsonSerializable.load(strctcfg,StrictConfig.class,new StrictConfig()); - swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig()); - nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig()); - violationConfig = JsonSerializable.load(violationcfg,ViolationConfig.class,new ViolationConfig()); + getLogger().info("Deleting Residual Block Displays"); + List worlds = Bukkit.getWorlds(); + List entities = new ArrayList<>(); + for (World world : worlds) { + entities.addAll(world.getEntities().stream().filter(entity -> entity.getScoreboardTags().contains("./Sentinel/ Block Display")).toList()); + entities.forEach(Entity::remove); + } - // Save - mainConfig.save(); - advConfig.save(); - fpConfig.save(); - strictConfig.save(); - swearConfig.save(); - nbtConfig.save(); - violationConfig.save(); - - whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage()); - whitelist.save(); - - log.info("Loading Dictionary (%s)...".formatted(Sentinel.mainConfig.plugin.lang)); - - lang = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile()); - lang.save(); - - log.info("Setting License Key"); - license = Auth.getLicenseKey(); + director.launch(); } @Override public void onDisable() { // Plugin shutdown logic PacketEvents.getAPI().terminate(); - log.info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion())); + getLogger().info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion())); } public static Sentinel getInstance() { return instance; } + + public Director getDirector() { + return director; + } - public static File dataFolder() { - return dataFolder; + public NamespacedKey getNamespace(String key) { + return new NamespacedKey(Sentinel.getInstance(), key); } } diff --git a/src/main/java/me/trouper/sentinel/data/IO.java b/src/main/java/me/trouper/sentinel/data/IO.java new file mode 100644 index 0000000..ae63fda --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/IO.java @@ -0,0 +1,68 @@ +package me.trouper.sentinel.data; + +import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.config.*; +import me.trouper.sentinel.data.config.lang.LanguageFile; +import me.trouper.sentinel.data.storage.ExtraStorage; +import me.trouper.sentinel.data.storage.CommandBlockStorage; + +import java.io.File; + +public class IO { + private final File dataFolder = new File("plugins/SentinelAntiNuke"); + private final File violationcfg = new File(dataFolder,"/violation-config.json"); + private final File cfgfile = new File(dataFolder,"/main-config.json"); + private final File nbtcfg = new File(dataFolder, "/nbt-config.json"); + private final File strctcfg = new File(dataFolder, "/strict.json"); + private final File swrcfg = new File(dataFolder, "/swears.json"); + private final File fpcfg = new File(dataFolder, "/false-positives.json"); + private final File advcfg = new File(dataFolder, "/advanced-config.json"); + private final File cmdWhitelist = new File(dataFolder, "/storage/whitelist.json"); + private final File extraFile = new File(dataFolder, "/storage/extra.json"); + + public LanguageFile lang; + public ViolationConfig violationConfig = JsonSerializable.load(violationcfg, ViolationConfig.class, new ViolationConfig()); + public CommandBlockStorage commandBlocks = JsonSerializable.load(cmdWhitelist, CommandBlockStorage.class, new CommandBlockStorage()); + public ExtraStorage extraStorage = JsonSerializable.load(cmdWhitelist, ExtraStorage.class, new ExtraStorage()); + public MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig()); + public FPConfig fpConfig = JsonSerializable.load(fpcfg, FPConfig.class, new FPConfig()); + public SwearsConfig swearConfig = JsonSerializable.load(swrcfg, SwearsConfig.class, new SwearsConfig()); + public StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig()); + public NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig()); + public AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig()); + + public void loadConfig() { + // Init + mainConfig = JsonSerializable.load(cfgfile,MainConfig.class,new MainConfig()); + advConfig = JsonSerializable.load(advcfg,AdvancedConfig.class,new AdvancedConfig()); + fpConfig = JsonSerializable.load(fpcfg,FPConfig.class,new FPConfig()); + strictConfig = JsonSerializable.load(strctcfg,StrictConfig.class,new StrictConfig()); + swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig()); + nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig()); + violationConfig = JsonSerializable.load(violationcfg,ViolationConfig.class,new ViolationConfig()); + + // Save + mainConfig.save(); + advConfig.save(); + fpConfig.save(); + strictConfig.save(); + swearConfig.save(); + nbtConfig.save(); + violationConfig.save(); + + commandBlocks = JsonSerializable.load(cmdWhitelist, CommandBlockStorage.class, new CommandBlockStorage()); + extraStorage = JsonSerializable.load(extraFile, ExtraStorage.class, new ExtraStorage()); + commandBlocks.save(); + extraStorage.save(); + + Sentinel.getInstance().getLogger().info("Loading Dictionary (%s)...".formatted(mainConfig.plugin.lang)); + + lang = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile()); + lang.save(); + } + + public File getDataFolder() { + return dataFolder; + } +} diff --git a/src/main/java/me/trouper/sentinel/data/WhitelistStorage.java b/src/main/java/me/trouper/sentinel/data/WhitelistStorage.java deleted file mode 100644 index 7e18029..0000000 --- a/src/main/java/me/trouper/sentinel/data/WhitelistStorage.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.trouper.sentinel.data; - -import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.types.WhitelistedBlock; - -import java.io.File; -import java.util.concurrent.ConcurrentLinkedQueue; - -public class WhitelistStorage implements JsonSerializable { - @Override - public File getFile() { - File file = new File(Sentinel.dataFolder(), "/storage/whitelist.json"); - file.getParentFile().mkdirs(); - return file; - } - - public ConcurrentLinkedQueue whitelistedCMDBlocks = new ConcurrentLinkedQueue<>(); - -} diff --git a/src/main/java/me/trouper/sentinel/data/config/AdvancedConfig.java b/src/main/java/me/trouper/sentinel/data/config/AdvancedConfig.java index dda05e5..303f1ac 100644 --- a/src/main/java/me/trouper/sentinel/data/config/AdvancedConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/AdvancedConfig.java @@ -10,11 +10,11 @@ import java.util.List; import java.util.Map; public class AdvancedConfig implements JsonSerializable { - public static String nonce = "%%__NONCE__%%"; + public transient String nonce = "%%__NONCE__%%"; @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/advanced-config.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/advanced-config.json"); file.getParentFile().mkdirs(); return file; } diff --git a/src/main/java/me/trouper/sentinel/data/config/FPConfig.java b/src/main/java/me/trouper/sentinel/data/config/FPConfig.java index ec6bb92..e2fd637 100644 --- a/src/main/java/me/trouper/sentinel/data/config/FPConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/FPConfig.java @@ -12,7 +12,7 @@ public class FPConfig implements JsonSerializable { @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/false-positives.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/false-positives.json"); file.getParentFile().mkdirs(); return file; } diff --git a/src/main/java/me/trouper/sentinel/data/config/MainConfig.java b/src/main/java/me/trouper/sentinel/data/config/MainConfig.java index 0245c35..f5106af 100644 --- a/src/main/java/me/trouper/sentinel/data/config/MainConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/MainConfig.java @@ -9,12 +9,12 @@ import java.util.List; public class MainConfig implements JsonSerializable { - public static String user = "%%__USER__%%"; - public static String username = "%%__USERNAME__%%"; + public transient String user = "%%__USER__%%"; + public transient String username = "%%__USERNAME__%%"; @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/main-config.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/main-config.json"); file.getParentFile().mkdirs(); return file; } @@ -23,8 +23,8 @@ public class MainConfig implements JsonSerializable { public boolean telemetry = true; public Plugin plugin = new Plugin(); - public Chat chat = new Chat(); public BackdoorDetection backdoorDetection = new BackdoorDetection(); + public Chat chat = new Chat(); public class Plugin { public String license = "null"; @@ -34,7 +34,7 @@ public class MainConfig implements JsonSerializable { public List trustedPlayers = Arrays.asList( "049460f7-21cb-42f5-8059-d42752bf406f" ); - + public boolean antiBan = true; public boolean reopCommand = false; public boolean pluginHider = true; public String identifier = "My Server (Edit in main-config.json)"; @@ -96,7 +96,7 @@ public class MainConfig implements JsonSerializable { public boolean enabled = true; public boolean silent = false; public boolean punished = false; - public String regex = "[^A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_]"; + public String regex = "[^A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_ ]"; public List punishCommands = Arrays.asList( "clearchat", "mute %player% 1m Please refrain from spamming!" diff --git a/src/main/java/me/trouper/sentinel/data/config/NBTConfig.java b/src/main/java/me/trouper/sentinel/data/config/NBTConfig.java index 2c3c2f1..368cc6f 100644 --- a/src/main/java/me/trouper/sentinel/data/config/NBTConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/NBTConfig.java @@ -8,7 +8,7 @@ import java.io.File; public class NBTConfig implements JsonSerializable { @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/nbt-config.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/nbt-config.json"); file.getParentFile().mkdirs(); return file; } @@ -17,6 +17,10 @@ public class NBTConfig implements JsonSerializable { public boolean allowLore = true; public boolean allowAttributes = false; public boolean allowPotions = false; + public boolean allowCustomConsumables = false; + public boolean allowCustomTools = false; + public boolean allowBooks = false; + public boolean allowRecursion = true; public int globalMaxEnchant = 5; public int maxMending = 1; public int maxUnbreaking = 3; diff --git a/src/main/java/me/trouper/sentinel/data/config/StrictConfig.java b/src/main/java/me/trouper/sentinel/data/config/StrictConfig.java index 7c00cab..3a1d57e 100644 --- a/src/main/java/me/trouper/sentinel/data/config/StrictConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/StrictConfig.java @@ -11,7 +11,7 @@ import java.util.List; public class StrictConfig implements JsonSerializable { @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/strict.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/strict.json"); file.getParentFile().mkdirs(); return file; } diff --git a/src/main/java/me/trouper/sentinel/data/config/SwearsConfig.java b/src/main/java/me/trouper/sentinel/data/config/SwearsConfig.java index 99ec70f..dfa66fb 100644 --- a/src/main/java/me/trouper/sentinel/data/config/SwearsConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/SwearsConfig.java @@ -10,7 +10,7 @@ import java.util.List; public class SwearsConfig implements JsonSerializable { @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/swears.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/swears.json"); file.getParentFile().mkdirs(); return file; } diff --git a/src/main/java/me/trouper/sentinel/data/config/ViolationConfig.java b/src/main/java/me/trouper/sentinel/data/config/ViolationConfig.java index 13cec4f..122ebb7 100644 --- a/src/main/java/me/trouper/sentinel/data/config/ViolationConfig.java +++ b/src/main/java/me/trouper/sentinel/data/config/ViolationConfig.java @@ -10,20 +10,107 @@ import java.util.List; public class ViolationConfig implements JsonSerializable { @Override public File getFile() { - File file = new File(Sentinel.dataFolder(), "/violation-config.json"); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/violation-config.json"); file.getParentFile().mkdirs(); return file; } public CommandBlockEdit commandBlockEdit = new CommandBlockEdit(); - public CommandBlockExecute commandBlockExecute = new CommandBlockExecute(); + public CommandBlockWhitelist commandBlockWhitelist = new CommandBlockWhitelist(); public CommandBlockMinecartPlace commandBlockMinecartPlace = new CommandBlockMinecartPlace(); public CommandBlockMinecartUse commandBlockMinecartUse = new CommandBlockMinecartUse(); + public CommandBlockMinecartBreak commandBlockMinecartBreak = new CommandBlockMinecartBreak(); public CommandBlockPlace commandBlockPlace = new CommandBlockPlace(); public CommandBlockUse commandBlockUse = new CommandBlockUse(); + public CommandBlockBreak commandBlockBreak = new CommandBlockBreak(); public CommandExecute commandExecute = new CommandExecute(); public CreativeHotbarAction creativeHotbarAction = new CreativeHotbarAction(); + public StructureBlockPlace structureBlockPlace = new StructureBlockPlace(); + public StructureBlockBreak structureBlockBreak = new StructureBlockBreak(); + public StructureBlockUse structureBlockUse = new StructureBlockUse(); + public JigsawBlockPlace jigsawBlockPlace = new JigsawBlockPlace(); + public JigsawBlockBreak jigsawBlockBreak = new JigsawBlockBreak(); + public JigsawBlockUse jigsawBlockUse = new JigsawBlockUse(); + public class JigsawBlockPlace { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class JigsawBlockBreak { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class JigsawBlockUse { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class StructureBlockPlace { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class StructureBlockBreak { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class StructureBlockUse { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class CommandBlockMinecartBreak { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } + + public class CommandBlockBreak { + public boolean enabled = true; + public boolean deop = true; + public boolean logToDiscord = true; + public boolean punish = false; + public List punishmentCommands = Arrays.asList( + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); + } public class CommandBlockEdit { public boolean enabled = true; @@ -81,7 +168,7 @@ public class ViolationConfig implements JsonSerializable { public boolean logToDiscord = true; public boolean punish = false; public List punishmentCommands = Arrays.asList( - "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + "gamemode survival %player%" ); } @@ -113,7 +200,9 @@ public class ViolationConfig implements JsonSerializable { "pluginmanager", "rl", "reload", - "plugman" + "plugman", + "spigot", + "paper" ); public boolean deop = true; public boolean logToDiscord = true; @@ -137,14 +226,24 @@ public class ViolationConfig implements JsonSerializable { public List punishmentCommands = Arrays.asList( "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." ); + public List whitelist = Arrays.asList( + "pluginwithstupidgui:callback" + ); } } - public class CommandBlockExecute { + public class CommandBlockWhitelist { public boolean enabled = true; public boolean destroyBlock = false; + public boolean destroyCart = false; public boolean attemptRestore = true; public boolean logToDiscord = false; + public List disabledCommands = Arrays.asList( + "op", + "deop", + "minecraft:op", + "minecraft:deop" + ); } } diff --git a/src/main/java/me/trouper/sentinel/data/config/lang/LanguageFile.java b/src/main/java/me/trouper/sentinel/data/config/lang/LanguageFile.java index c00f162..02472b6 100644 --- a/src/main/java/me/trouper/sentinel/data/config/lang/LanguageFile.java +++ b/src/main/java/me/trouper/sentinel/data/config/lang/LanguageFile.java @@ -6,7 +6,7 @@ import me.trouper.sentinel.Sentinel; import java.io.File; public class LanguageFile implements JsonSerializable { - public static final File PATH = new File(Sentinel.dataFolder(), "/lang/" + Sentinel.mainConfig.plugin.lang); + public static final File PATH = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/lang/" + Sentinel.getInstance().getDirector().io.mainConfig.plugin.lang); public LanguageFile() {} @Override @@ -180,13 +180,17 @@ public class LanguageFile implements JsonSerializable { public String use = "use"; public String edit = "edit"; public String place = "place"; + public String brake = "break"; public String run = "run"; public String grab = "grab"; // Types public String commandBlock = "Command Block"; - public String minecartCommandBlock = "Minecart Command Block"; + public String structureBlock = "Structure Block"; + public String jigsawBlock = "Jigsaw Block"; + public String commandMinecart = "Command Minecart"; public String commandBlockWhitelist = "Command Block Whitelist"; + public String commandBlockRestriction = "Command Block Restriction"; public String specificCommand = "Specific Command"; public String loggedCommand = "Logged Command"; public String dangerousCommand = "Dangerous Command"; diff --git a/src/main/java/me/trouper/sentinel/data/storage/CommandBlockStorage.java b/src/main/java/me/trouper/sentinel/data/storage/CommandBlockStorage.java new file mode 100644 index 0000000..8390fdb --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/storage/CommandBlockStorage.java @@ -0,0 +1,35 @@ +package me.trouper.sentinel.data.storage; + +import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.data.types.SerialLocation; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CommandBlockStorage implements JsonSerializable { + @Override + public File getFile() { + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/storage/whitelist.json"); + file.getParentFile().mkdirs(); + return file; + } + + public List holders = new ArrayList<>() { + @Override + public boolean add(CommandBlockHolder holder) { + for (CommandBlockHolder existing : holders) { + if (existing.loc().isSameLocation(holder.loc())) { + super.remove(existing); + } + } + + return super.add(holder); + } + }; + +} diff --git a/src/main/java/me/trouper/sentinel/data/storage/ExtraStorage.java b/src/main/java/me/trouper/sentinel/data/storage/ExtraStorage.java new file mode 100644 index 0000000..c419de4 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/storage/ExtraStorage.java @@ -0,0 +1,20 @@ +package me.trouper.sentinel.data.storage; + +import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.SerialLocation; + +import java.io.File; +import java.util.*; + +public class ExtraStorage implements JsonSerializable { + @Override + public File getFile() { + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/storage/extra.json"); + file.getParentFile().mkdirs(); + return file; + } + + public Map shadowRealm = new HashMap<>(); + +} diff --git a/src/main/java/me/trouper/sentinel/data/types/CMDBlockType.java b/src/main/java/me/trouper/sentinel/data/types/CMDBlockType.java deleted file mode 100644 index 3fcd6ca..0000000 --- a/src/main/java/me/trouper/sentinel/data/types/CMDBlockType.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.trouper.sentinel.data.types; - -public enum CMDBlockType { - CHAIN, - REPEAT, - IMPULSE, -} diff --git a/src/main/java/me/trouper/sentinel/data/types/CommandBlockHolder.java b/src/main/java/me/trouper/sentinel/data/types/CommandBlockHolder.java new file mode 100644 index 0000000..eb3cfad --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/types/CommandBlockHolder.java @@ -0,0 +1,199 @@ +package me.trouper.sentinel.data.types; + +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.CommandBlock; +import org.bukkit.command.Command; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.persistence.PersistentDataType; + +public class CommandBlockHolder { + + private final String owner; + private final SerialLocation loc; + private final String facing; + private final String type; + private final boolean auto; + private final boolean conditional; + private final String command; + private boolean whitelisted; + + public CommandBlockHolder(String owner, SerialLocation loc, String facing, String type, boolean auto, boolean conditional, String command) { + this.owner = owner; + this.loc = loc; + this.facing = facing; + this.type = type; + this.auto = auto; + this.conditional = conditional; + this.command = command; + this.whitelisted = false; + } + + public String owner() { + return owner; + } + + public SerialLocation loc() { + return loc; + } + + public String facing() { + return facing; + } + + public String type() { + return type; + } + + public boolean auto() { + return auto; + } + + public boolean conditional() { + return conditional; + } + + public String command() { + return command; + } + + public boolean present() { + if (this.loc.isUUID()) { + Entity cart = Bukkit.getEntity(this.loc.toUIID()); + if (!(cart instanceof CommandMinecart cm)) return false; + return this.command.equals(cm.getCommand()); + } else { + Location where = loc.translate(); + boolean preLoaded = where.isChunkLoaded(); + where.getChunk().load(false); + Block b = where.getBlock(); + if (!(b.getState() instanceof CommandBlock c) || !(b.getBlockData() instanceof org.bukkit.block.data.type.CommandBlock cb)) { + ServerUtils.verbose("Block is not present due to not being a command block."); + if (!this.whitelisted) this.delete(); + return false; + } + if (!this.command.equals(c.getCommand())) { + ServerUtils.verbose("Block is not present due to command mismatch. Should be '%s', is '%s'",this.command,c.getCommand()); + if (!this.whitelisted) this.delete(); + return false; + } + if (this.conditional != cb.isConditional()) { + ServerUtils.verbose("Block is not present due to conditional mismatch."); + if (!this.whitelisted) this.delete(); + return false; + } + if (!this.getType().equals(c.getType())) { + ServerUtils.verbose("Block is not present due to type mismatch. Should be '%s', is '%s'",this.type,c.getType()); + if (!this.whitelisted) this.delete(); + return false; + } + if (this.auto != (c.getPersistentDataContainer().getOrDefault(Sentinel.getInstance().getNamespace("auto"), PersistentDataType.BYTE,(byte) 0) == (byte) 1)) { + ServerUtils.verbose("Block is not present due to auto mismatch."); + if (!this.whitelisted) this.delete(); + return false; + } + if (!preLoaded) where.getChunk().unload(); + return true; + } + } + + public boolean whitelisted() { + return whitelisted; + } + + public CommandBlockHolder setWhitelisted(boolean whitelisted) { + this.whitelisted = whitelisted; + return this; + } + + public CommandBlockHolder addAndWhitelist() { + return setWhitelisted(true).add(); + } + + public BlockFace getDirection() { + try { + return BlockFace.valueOf(facing.toUpperCase()); + } catch (IllegalArgumentException e) { + return BlockFace.NORTH; + } + } + + public Material getType() { + return switch (this.type) { + case "COMMAND_BLOCK" -> Material.COMMAND_BLOCK; + case "REPEATING_COMMAND_BLOCK" -> Material.REPEATING_COMMAND_BLOCK; + case "CHAIN_COMMAND_BLOCK" -> Material.CHAIN_COMMAND_BLOCK; + case "COMMAND_BLOCK_MINECART" -> Material.COMMAND_BLOCK_MINECART; + default -> throw new IllegalArgumentException("Unknown command block type: " + type); + }; + } + + public void destroy() { + SerialLocation.translate(this.loc).getBlock().setType(Material.AIR); + if (!whitelisted) delete(); + } + + public boolean restore() { + if (Material.COMMAND_BLOCK_MINECART.equals(this.getType())) { + ServerUtils.verbose("Cannot restore minecarts yet."); + return false; + } + + if (this.present()) return false; + + Block block = SerialLocation.translate(this.loc).getBlock(); + block.setType(this.getType()); + if (!ServerUtils.isCommandBlock(block)) { + ServerUtils.verbose("Block at the location was not a command block (You shouldn't be seeing this. Report it)."); + return false; + } + + CommandBlock cb = (CommandBlock) block.getState(); + + cb.setCommand(this.command()); + block.setType(this.getType()); + block.getState().update(true, false); + + org.bukkit.block.data.type.CommandBlock conditional = (org.bukkit.block.data.type.CommandBlock) cb.getBlock().getBlockData(); + ServerUtils.verbose("Direction is " + this.getDirection()); + ServerUtils.verbose("Conditional is " + this.conditional); + + conditional.setFacing(this.getDirection()); + conditional.setConditional(this.conditional); + + cb.setBlockData(conditional); + + cb.getPersistentDataContainer().set( + Sentinel.getInstance().getNamespace("auto"), + PersistentDataType.BYTE, + this.auto ? (byte) 1 : (byte) 0 + ); + + cb.update(true,false); + ServerUtils.verbose("Command block at " + this.loc.toString() + " has been restored."); + return true; + } + + public boolean isCart() { + return loc.isUUID(); + } + + public CommandBlockHolder add() { + Sentinel.getInstance().getDirector().io.commandBlocks.holders.add(this); + Sentinel.getInstance().getDirector().io.commandBlocks.save(); + return this; + } + + public void delete() { + Sentinel.getInstance().getDirector().io.commandBlocks.holders.removeIf(h->h.loc.isSameLocation(this.loc)); + Sentinel.getInstance().getDirector().io.commandBlocks.save(); + } +} diff --git a/src/main/java/me/trouper/sentinel/data/Emojis.java b/src/main/java/me/trouper/sentinel/data/types/Emojis.java similarity index 98% rename from src/main/java/me/trouper/sentinel/data/Emojis.java rename to src/main/java/me/trouper/sentinel/data/types/Emojis.java index 13a1d0c..bab6afd 100644 --- a/src/main/java/me/trouper/sentinel/data/Emojis.java +++ b/src/main/java/me/trouper/sentinel/data/types/Emojis.java @@ -1,4 +1,4 @@ -package me.trouper.sentinel.data; +package me.trouper.sentinel.data.types; public class Emojis { public static String space = "<:space:1210008300515762238>"; diff --git a/src/main/java/me/trouper/sentinel/data/types/IPLocation.java b/src/main/java/me/trouper/sentinel/data/types/IPLocation.java new file mode 100644 index 0000000..c69f12e --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/types/IPLocation.java @@ -0,0 +1,180 @@ +package me.trouper.sentinel.data.types; + +public class IPLocation { + private String country; + private String countryCode; + private String region; + private String regionCode; + private String city; + private String district; + private String zip; + private String lat; + private String lon; + private String timezone; + private String isp; + private String org; + private String as; + private String reverse; + private boolean isMobile; + private boolean isProxied; + private boolean isHosted; + + + public IPLocation(String country, String countryCode, String region, String regionCode, String city, String district, String zip, String lat, String lon, String timezone, String isp, String org, String as, String reverse, boolean isMobile, boolean isProxied, boolean isHosted) { + this.country = country; + this.countryCode = countryCode; + this.region = region; + this.regionCode = regionCode; + this.city = city; + this.district = district; + this.zip = zip; + this.lat = lat; + this.lon = lon; + this.timezone = timezone; + this.isp = isp; + this.org = org; + this.as = as; + this.reverse = reverse; + this.isMobile = isMobile; + this.isProxied = isProxied; + this.isHosted = isHosted; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getRegionCode() { + return regionCode; + } + + public void setRegionCode(String regionCode) { + this.regionCode = regionCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getDistrict() { + return district; + } + + public void setDistrict(String district) { + this.district = district; + } + + public String getZip() { + return zip; + } + + public void setZip(String zip) { + this.zip = zip; + } + + public String getLat() { + return lat; + } + + public void setLat(String lat) { + this.lat = lat; + } + + public String getLon() { + return lon; + } + + public void setLon(String lon) { + this.lon = lon; + } + + public String getTimezone() { + return timezone; + } + + public void setTimezone(String timezone) { + this.timezone = timezone; + } + + public String getIsp() { + return isp; + } + + public void setIsp(String isp) { + this.isp = isp; + } + + public String getOrg() { + return org; + } + + public void setOrg(String org) { + this.org = org; + } + + public String getAs() { + return as; + } + + public void setAs(String as) { + this.as = as; + } + + public String getReverse() { + return reverse; + } + + public void setReverse(String reverse) { + this.reverse = reverse; + } + + public boolean isMobile() { + return isMobile; + } + + public void setMobile(boolean mobile) { + isMobile = mobile; + } + + public boolean isProxied() { + return isProxied; + } + + public void setProxied(boolean proxied) { + isProxied = proxied; + } + + public boolean isHosted() { + return isHosted; + } + + public void setHosted(boolean hosted) { + isHosted = hosted; + } +} + + diff --git a/src/main/java/me/trouper/sentinel/data/types/Location.java b/src/main/java/me/trouper/sentinel/data/types/Location.java deleted file mode 100644 index cbf4c81..0000000 --- a/src/main/java/me/trouper/sentinel/data/types/Location.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.trouper.sentinel.data.types; - -public record Location(String world, double x, double y,double z) { -} diff --git a/src/main/java/me/trouper/sentinel/data/types/Selection.java b/src/main/java/me/trouper/sentinel/data/types/Selection.java new file mode 100644 index 0000000..7d2f63c --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/types/Selection.java @@ -0,0 +1,68 @@ +package me.trouper.sentinel.data.types; + +import me.trouper.sentinel.utils.display.BlockDisplayRaytracer; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +public class Selection { + + private Location pos1; + private Location pos2; + + public void setPos1(Location loc) { this.pos1 = loc; } + public void setPos2(Location loc) { this.pos2 = loc; } + + public Location getPos1() { return pos1; } + public Location getPos2() { return pos2; } + + public boolean isComplete() { + return pos1 != null && pos2 != null; + } + + public void forEachBlock(Consumer action) { + for (Block block : getBlocks()) { + action.accept(block); + } + } + + public Set getBlocks() { + Location pos1 = this.getPos1(); + Location pos2 = this.getPos2(); + + World world = pos1.getWorld(); + int minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); + int minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); + int minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); + int maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); + int maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()); + int maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); + + Set blocks = new HashSet<>(); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + blocks.add(world.getBlockAt(x,y,z)); + } + } + } + + return blocks; + } + + public void display(Player beholder) { + if (!beholder.isOnline() + || this.pos1 == null + || this.pos2 == null + || (beholder.getLocation().distance(this.pos1) > 64 && beholder.getLocation().distance(this.pos2) > 64)) return; + BlockDisplayRaytracer.outline(Material.LIGHT_BLUE_STAINED_GLASS,this.getPos1(),this.getPos2(),0.1,2, List.of(beholder)); + } +} diff --git a/src/main/java/me/trouper/sentinel/data/types/SerialLocation.java b/src/main/java/me/trouper/sentinel/data/types/SerialLocation.java new file mode 100644 index 0000000..5122536 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/types/SerialLocation.java @@ -0,0 +1,65 @@ +package me.trouper.sentinel.data.types; + +import me.trouper.sentinel.utils.MathUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.UUID; + +public record SerialLocation(String world, double x, double y, double z) { + public static Location translate(SerialLocation loc) { + World w = Bukkit.getWorld(loc.world()); + return new Location(w,loc.x(),loc.y(),loc.z()); + } + + public static SerialLocation translate(Location loc) { + return new SerialLocation(loc.getWorld().getName(),loc.x(),loc.y(),loc.z()); + } + + public Location translate() { + return translate(this); + } + + public UUID toUIID() { + return toUUID(this); + } + + public boolean isUUID() { + return this.world.equals("./Sentinel/ UUID$"); + } + + public boolean isSameLocation(Location loc) { + if (this.isUUID()) return false; + Location thisLoc = this.translate(); + return thisLoc.getWorld().equals(loc.getWorld()) && + thisLoc.getBlockX() == loc.getBlockX() && + thisLoc.getBlockY() == loc.getBlockY() && + thisLoc.getBlockZ() == loc.getBlockZ(); + } + + public boolean isSameLocation(SerialLocation loc) { + if (this.isUUID() && loc.isUUID()) { + return loc.toUIID().equals(this.toUIID()); + } else if (this.isUUID() ^ loc.isUUID()) { + return false; + } + return this.world.equals(loc.world) && + (int) this.x == (int) loc.x && + (int) this.y == (int) loc.y && + (int) this.z == (int) loc.z; + } + + public static UUID toUUID(SerialLocation loc) { + if (!loc.world.equals("./Sentinel/ UUID$")) throw new IllegalArgumentException("You can only get UUIDs from locations which hold them."); + return MathUtils.doublesToUuid(new double[]{loc.x,loc.y,loc.z}); + } + + public static SerialLocation uuidToLocation(UUID uuid) { + double[] doubles = MathUtils.uuidToDoubles(uuid); + return new SerialLocation("./Sentinel/ UUID$",doubles[0],doubles[1],doubles[2]); + } +} diff --git a/src/main/java/me/trouper/sentinel/data/types/Test.java b/src/main/java/me/trouper/sentinel/data/types/Test.java new file mode 100644 index 0000000..f2e95f3 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/data/types/Test.java @@ -0,0 +1,12 @@ +package me.trouper.sentinel.data.types; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.UUID; + +public class Test { + + + +} diff --git a/src/main/java/me/trouper/sentinel/data/types/WhitelistedBlock.java b/src/main/java/me/trouper/sentinel/data/types/WhitelistedBlock.java deleted file mode 100644 index 46b272a..0000000 --- a/src/main/java/me/trouper/sentinel/data/types/WhitelistedBlock.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.trouper.sentinel.data.types; - -import org.bukkit.Bukkit; -import org.bukkit.World; - -public record WhitelistedBlock(String owner, Location loc, String type, boolean active, String command) { - - public static org.bukkit.Location fromSerialized(Location loc) { - World w = Bukkit.getWorld(loc.world()); - return new org.bukkit.Location(w,loc.x(),loc.y(),loc.z()); - } - public static Location serialize(org.bukkit.Location loc) { - return new Location(loc.getWorld().getName(),loc.x(),loc.y(),loc.z()); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/commands/CallbackCommand.java b/src/main/java/me/trouper/sentinel/server/commands/CallbackCommand.java index d2f822f..4d707e0 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/CallbackCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/CallbackCommand.java @@ -7,7 +7,7 @@ import io.github.itzispyder.pdk.commands.Permission; import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.itzispyder.pdk.utils.misc.Cooldown; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; +import me.trouper.sentinel.server.functions.helpers.ReportHandler; import me.trouper.sentinel.server.functions.helpers.Report; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.Text; @@ -29,18 +29,18 @@ public class CallbackCommand implements CustomCommand { case "fpreport" -> { if (!PlayerUtils.checkPermission(sender,"sentinel.callbacks.fpreport")) return; if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) { - p.sendMessage(Text.prefix(Sentinel.lang.cooldown.onCooldown + fpReportCooldown.getCooldown(p.getUniqueId()))); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.cooldown.onCooldown + fpReportCooldown.getCooldown(p.getUniqueId()))); return; } long id = args.get(1).toLong(); - Report report = FalsePositiveReporting.reports.get(id); + Report report = Sentinel.getInstance().getDirector().reportHandler.reports.get(id); if (report == null) { - p.sendMessage(Text.prefix(Sentinel.lang.reports.noReport)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.reports.noReport)); return; } - p.sendMessage(Text.prefix(Sentinel.lang.reports.reportingFalsePositive)); - FalsePositiveReporting.sendReport(p,report); - p.sendMessage(Text.prefix(Sentinel.lang.reports.falsePositiveSuccess)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.reports.reportingFalsePositive)); + Sentinel.getInstance().getDirector().reportHandler.sendReport(p,report); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.reports.falsePositiveSuccess)); } } } diff --git a/src/main/java/me/trouper/sentinel/server/commands/ExtraCommand.java b/src/main/java/me/trouper/sentinel/server/commands/ExtraCommand.java new file mode 100644 index 0000000..0eefffa --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/commands/ExtraCommand.java @@ -0,0 +1,237 @@ +package me.trouper.sentinel.server.commands; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.play.server.*; +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.Permission; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.IPLocation; +import me.trouper.sentinel.data.types.SerialLocation; +import me.trouper.sentinel.server.events.extras.ShadowRealmEvents; +import me.trouper.sentinel.utils.IPUtils; +import me.trouper.sentinel.utils.ImageUtils; +import me.trouper.sentinel.utils.Random; +import me.trouper.sentinel.utils.Text; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerKickEvent; + +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +@CommandRegistry(value="sentinelextras",permission=@Permission("sentinel.extras")) +public class ExtraCommand implements CustomCommand { + @Override + public void dispatchCommand(CommandSender sender, Command command, String s, Args args) { + if (args.getSize() < 2) { + sender.sendMessage(Text.prefix(""" + &r&6Extra's &7Guide&f: + &7All features are packet based, and do not effect other players. + &bSyntax&f: &7/sentinelextras + &7Features&f: + &7 - &bfree&f: &7Release player from shadow realm. + &7 - &balfa&f: &7Reliable, crash player. + &7 - &bbravo&f: &7Reliable, send player to shadow realm. + &7 - &bcharlie&f: &7Reliable, delete player. + &7 - &bdelta&f: &7Reliable, Lock player's mouse. + &7 - &becho&f: &7Unreliable, Inflate player's log. + &7 - &bfoxtrot&f: &7Unreliable, Spam player with titles. + &7 - &bgolf&f: &7Reliable, corrupt player chunks. + &7 - &bhotel&f: &7Reliable, spam player with bogus entities. + &7 - &bindia&f: &7Reliable, kick with no back to server list button. + &7 - &bjuliett&f: &7Reliable, make player's screen dim rapidly. + """)); + return; + } + String target = args.get(1).toString(); + Player victim = Bukkit.getPlayer(target); + if (victim == null || !victim.isOnline()) { + sender.sendMessage("You must pick an online player."); + return; + } + switch (args.get(0).toString()) { + case "free" -> freePlayer(sender, victim, target); + case "alfa" -> crashPlayer(sender, victim, target); + case "bravo" -> sendToShadowRealm(sender, victim, target); + case "charlie" -> deletePlayer(sender, victim, target); + case "delta" -> freezePlayer(sender, victim, target); + case "echo" -> inflatePlayerLog(sender, victim, target); + case "foxtrot" -> spamPlayerWithTitles(sender, victim, target); + case "golf" -> corruptPlayerChunks(sender, victim, target); + case "hotel" -> spamPlayerWithEntities(sender, victim, target); + case "india" -> kickPlayerWithoutBackButton(sender, victim, target); + case "juliett" -> makePlayerDrowsy(sender,victim,target); + } + } + + @Override + public void dispatchCompletions(CommandSender commandSender, Command command, String s, CompletionBuilder b) { + b.then(b.arg("info")); + b.then(b.arg("free", "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliett", "kilo", "lima").then( + b.argOnlinePlayers() + )); + } + + private void makePlayerDrowsy(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + player.sendPacket(new WrapperPlayServerEntityAnimation(victim.getEntityId(), WrapperPlayServerEntityAnimation.EntityAnimationType.WAKE_UP)); + }, 1, 1); + sender.sendMessage(Text.prefix("%s is getting very eepy.".formatted(target))); + } + + private void freePlayer(CommandSender sender, Player victim, String target) { + if (Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(victim.getUniqueId())) { + Location to = SerialLocation.translate(Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.get(victim.getUniqueId())); + Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.remove(victim.getUniqueId()); + Sentinel.getInstance().getDirector().io.extraStorage.save(); + victim.teleport(to); + } + sender.sendMessage(Text.prefix("Released %s.".formatted(target))); + } + + private void crashPlayer(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + player.sendPacket(new WrapperPlayServerUpdateViewDistance(4000)); + sender.sendMessage(Text.prefix("Crashing %s.".formatted(target))); + } + + private void sendToShadowRealm(CommandSender sender, Player victim, String target) { + Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.put(victim.getUniqueId(), SerialLocation.translate(victim.getLocation())); + Sentinel.getInstance().getDirector().io.extraStorage.save(); + ShadowRealmEvents.enforce(victim); + sender.sendMessage(Text.prefix("Sending %s to the shadow realm.".formatted(target))); + } + + private void deletePlayer(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + player.sendPacket(new WrapperPlayServerDestroyEntities(victim.getEntityId())); + sender.sendMessage(Text.prefix("Deleting %s.".formatted(target))); + } + + private void freezePlayer(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + for (int i = 0; i < 35 * 9; i++) { + player.sendPacket(new WrapperPlayServerCloseWindow()); + player.sendPacket(new WrapperPlayServerChangeGameState(WrapperPlayServerChangeGameState.Reason.DEMO_EVENT, 0)); + } + }, 1, 1); + sender.sendMessage(Text.prefix("Freezing %s.".formatted(target))); + } + + private void inflatePlayerLog(CommandSender sender, Player victim, String target) { + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + for (int i = 0; i < 4000; i++) { + victim.sendMessage(":3 Baiiiiii!!!!"); + } + }, 1, 1); + sender.sendMessage(Text.prefix("Filling the logs of %s.".formatted(target))); + } + + private void spamPlayerWithTitles(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + for (int i = 0; i < 50; i++) { + StringBuilder message = new StringBuilder(String.valueOf(Random.generateID())); + for (int j = 0; j < 256; j++) { + message.append(String.valueOf(Random.generateID())); + } + player.sendPacket(new WrapperPlayServerTitle( + WrapperPlayServerTitle.TitleAction.SET_TITLE, + Component.text(message.toString()).style(Style.style().color(NamedTextColor.DARK_GREEN).decorate(TextDecoration.OBFUSCATED).build()).asComponent(), + Component.text(message.toString()).style(Style.style().color(NamedTextColor.DARK_GREEN).decorate(TextDecoration.OBFUSCATED).build()).asComponent(), + Component.text(message.toString()).style(Style.style().color(NamedTextColor.DARK_GREEN).decorate(TextDecoration.OBFUSCATED).build()).asComponent(), + 0, 10000, 0 + )); + } + }, 1, 1); + sender.sendMessage(Text.prefix("Flooding %s's screen.".formatted(target))); + } + + private void corruptPlayerChunks(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + for (int i = 0; i < 50; i++) { + int chunkX = (victim.getLocation().getBlockX() >> 4) + i; + int chunkZ = (victim.getLocation().getBlockZ() >> 4) + i; + player.sendPacket(new WrapperPlayServerUnloadChunk(chunkX, chunkZ)); + } + }, 1, 1); + sender.sendMessage(Text.prefix("Corrupting %s's chunks.".formatted(target))); + } + + private void spamPlayerWithEntities(CommandSender sender, Player victim, String target) { + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + AtomicInteger entityId = new AtomicInteger(999999); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(), (t) -> { + if (!victim.isOnline()) t.cancel(); + for (int i = 0; i < 50; i++) { + WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity( + entityId.getAndIncrement(), + Optional.of(UUID.randomUUID()), + EntityTypes.ENDER_DRAGON, + new Vector3d(victim.getLocation().getX(), victim.getLocation().getY(), victim.getLocation().getZ()), + 0F, + 0F, + 0F, + 0, + Optional.of(new Vector3d(0, 0, 0)) + ); + player.sendPacket(packet); + } + }, 1, 1); + sender.sendMessage(Text.prefix("Summoning entities on %s.".formatted(target))); + } + + private void kickPlayerWithoutBackButton(CommandSender sender, Player victim, String target) { + String beforeLines = "\n".repeat(15 * 100 + 3); + String afterLines = "\n".repeat(15 * 100); + + Component image = Component.text("\n"); + for (Component component : ImageUtils.makeImage("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/x1ksxaas.png")) { + image = image.appendNewline().append(component); + } + String header = "Sorry %1$s!\nLooks like you're a griefer... \n...and this is a decoy server\nYour presence has been recorded. \n\nHow's the weather in %2$s, %3$s? \n"; + String footer = "\n\nWant to try again?\n Nope. No back to server list for you.\n\nCopyright © 2025 Sentinel Anti Nuke. All rights reserved.\n"; + String name = victim.getName(); + String ip = IPUtils.extractIp(victim.getAddress().getAddress()); + IPLocation location = IPUtils.getLocation(ip); + String region = location.getRegion(); + String city = location.getCity(); + victim.kick(Component.text(beforeLines) + .append(Component.text( + header.formatted( + name, + city, + region + ))) + .append(image) + .append(Component.text( + footer + afterLines + ) + ), + PlayerKickEvent.Cause.ILLEGAL_ACTION); + sender.sendMessage(Text.prefix("Kicked %1$s and removed the back to server list button. Their IP was %2$s (%3$s %4$s)".formatted(target, ip, city, region))); + } + + +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/commands/MessageCommand.java b/src/main/java/me/trouper/sentinel/server/commands/MessageCommand.java index 9b79f42..51bdb46 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/MessageCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/MessageCommand.java @@ -6,7 +6,7 @@ import io.github.itzispyder.pdk.commands.CustomCommand; import io.github.itzispyder.pdk.commands.Permission; import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.Message; +import me.trouper.sentinel.server.functions.helpers.MessageHandler; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.Bukkit; @@ -24,11 +24,11 @@ public class MessageCommand implements CustomCommand { Player p = (Player) sender; Player r = null; if (args.getSize() == 0) { - p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noOnlinePlayer)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.playerInteraction.noOnlinePlayer)); return; } if (args.getSize() == 1) { - p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noMessageProvided)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.playerInteraction.noMessageProvided)); return; } r = Bukkit.getPlayer(args.get(0).toString()); @@ -36,8 +36,8 @@ public class MessageCommand implements CustomCommand { String msg = args.getAll(1).toString().trim(); if (PlayerUtils.checkPermission(sender,"sentinel.message") && r != null) { - Message.messagePlayer(p,r,msg); - } else if (r == null) p.sendMessage(Text.prefix((Sentinel.lang.playerInteraction.noOnlinePlayer))); + Sentinel.getInstance().getDirector().messageHandler.messagePlayer(p,r,msg); + } else if (r == null) p.sendMessage(Text.prefix((Sentinel.getInstance().getDirector().io.lang.playerInteraction.noOnlinePlayer))); } @Override diff --git a/src/main/java/me/trouper/sentinel/server/commands/ReopCommand.java b/src/main/java/me/trouper/sentinel/server/commands/ReopCommand.java index c8d2586..1061234 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/ReopCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/ReopCommand.java @@ -16,18 +16,18 @@ public class ReopCommand implements CustomCommand { @Override public void dispatchCommand(CommandSender sender, Command command, String s, Args args) { Player p = (Player) sender; - if (PlayerUtils.isTrusted(p) && Sentinel.mainConfig.plugin.reopCommand) { + if (PlayerUtils.isTrusted(p) && Sentinel.getInstance().getDirector().io.mainConfig.plugin.reopCommand) { if (!p.isOp()) { - p.sendMessage(Text.prefix(Sentinel.lang.permissions.elevatingPerms)); - Sentinel.log.info(Sentinel.lang.permissions.logElevatingPerms.formatted(p.getName())); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.elevatingPerms)); + Sentinel.getInstance().getLogger().info(Sentinel.getInstance().getDirector().io.lang.permissions.logElevatingPerms.formatted(p.getName())); p.setOp(true); } else { - p.sendMessage(Text.prefix(Sentinel.lang.permissions.alreadyOp)); - Sentinel.log.info(Sentinel.lang.permissions.logAlreadyOp.formatted(p.getName())); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.alreadyOp)); + Sentinel.getInstance().getLogger().info(Sentinel.getInstance().getDirector().io.lang.permissions.logAlreadyOp.formatted(p.getName())); p.setOp(true); } } else { - p.sendMessage(Text.prefix(Sentinel.lang.permissions.noTrust)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.noTrust)); } } diff --git a/src/main/java/me/trouper/sentinel/server/commands/ReplyCommand.java b/src/main/java/me/trouper/sentinel/server/commands/ReplyCommand.java index 8eeaf32..44f878d 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/ReplyCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/ReplyCommand.java @@ -6,7 +6,7 @@ import io.github.itzispyder.pdk.commands.CustomCommand; import io.github.itzispyder.pdk.commands.Permission; import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.Message; +import me.trouper.sentinel.server.functions.helpers.MessageHandler; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.command.Command; @@ -19,7 +19,7 @@ import java.util.UUID; @CommandRegistry(value = "reply", permission = @Permission("sentinel.reply"),printStackTrace = true) public class ReplyCommand implements CustomCommand { - public static Map replyMap = Message.replyMap; + public static Map replyMap = Sentinel.getInstance().getDirector().messageHandler.replyMap; @Override public void dispatchCommand(CommandSender sender, Command command, String s, Args args) { @@ -27,16 +27,16 @@ public class ReplyCommand implements CustomCommand { Player p = sender.getServer().getPlayer(name); UUID senderID = p.getUniqueId(); if (replyMap.get(senderID) == null) { - p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noReply)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.playerInteraction.noReply)); } Player r = sender.getServer().getPlayer(replyMap.get(senderID)); UUID reciverID = r.getUniqueId(); if (args.get(0).toString() == null) { - p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noMessageProvided)); + p.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.playerInteraction.noMessageProvided)); } String msg = args.getAll().toString(); if (PlayerUtils.checkPermission(sender,"sentinel.message")) { - Message.messagePlayer(p,r,msg); + Sentinel.getInstance().getDirector().messageHandler.messagePlayer(p,r,msg); replyMap.put(senderID,reciverID); } } diff --git a/src/main/java/me/trouper/sentinel/server/commands/SentinelCommand.java b/src/main/java/me/trouper/sentinel/server/commands/SentinelCommand.java index e31c13a..64a4245 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/SentinelCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/SentinelCommand.java @@ -8,15 +8,18 @@ import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.papermc.paper.chat.ChatRenderer; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.types.WhitelistedBlock; -import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager; +import me.trouper.sentinel.data.types.SerialLocation; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.server.events.admin.WandEvents; import me.trouper.sentinel.server.functions.chatfilter.profanity.ProfanityFilter; import me.trouper.sentinel.server.functions.chatfilter.spam.SpamFilter; import me.trouper.sentinel.server.functions.chatfilter.unicode.UnicodeFilter; import me.trouper.sentinel.server.functions.chatfilter.url.UrlFilter; +import me.trouper.sentinel.data.types.Selection; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.startup.Load; +import me.trouper.sentinel.startup.drm.Loader; import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import me.trouper.sentinel.utils.trees.ConsoleFormatter; import me.trouper.sentinel.utils.trees.EmbedFormatter; @@ -30,290 +33,408 @@ import org.bukkit.block.CommandBlock; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; -@CommandRegistry(value = "sentinel",permission = @Permission("sentinel.staff"),printStackTrace = true) +@CommandRegistry(value = "sentinel", permission = @Permission("sentinel.staff"), printStackTrace = true) public class SentinelCommand implements CustomCommand { + // Constants for usage messages + private static final String USAGE_SENTINEL = "Usage: /sentinel "; + private static final String USAGE_COMMANDBLOCK = "Usage: /sentinel commandblock "; + private static final String USAGE_SELECTION = "Usage: /sentinel commandblock selection "; + private static final String USAGE_RESTORE = "Usage: /sentinel commandblock restore "; + private static final String USAGE_CLEAR = "Usage: /sentinel commandblock clear "; + public static Map spyMap = new HashMap<>(); @Override public void dispatchCommand(CommandSender sender, Command command, String s, Args args) { try { - safety(sender,command,s,args); + processCommand(sender, command, s, args); } catch (IllegalArgumentException e) { - sender.sendMessage(Text.prefix(Sentinel.lang.plugin.invalidArgs)); + e.printStackTrace(); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.invalidArgs)); } } @Override - public void dispatchCompletions(CommandSender commandSender, Command command, String s, CompletionBuilder b) { + public void dispatchCompletions(CommandSender sender, Command command, String s, CompletionBuilder b) { b.then(b.arg("socialspy")); b.then(b.arg("config")); + b.then(b.arg("wand")); b.then(b.arg("reload")); - b.then(b.arg("false-positive").then(b.arg("add","remove"))); - b.then(b.arg("debug").then( - b.arg("lang","toggle","chat"))); - b.then(b.arg("commandblock","cb").then(b.arg("add","remove","auto")) + b.then(b.arg("false-positive").then(b.arg("add", "remove"))); + b.then(b.arg("debug").then(b.arg("lang", "toggle", "chat"))); + b.then(b.arg("commandblock", "cb").then( + b.arg("add", "remove", "auto")) + .then(b.arg("selection") + .then(b.arg("add", "remove", "delete", "deselect", "pos1", "pos2"))) .then(b.arg("restore") - .then(b.arg("","all"))) + .then(b.arg("", "all"))) .then(b.arg("clear") - .then(b.arg("","all")))); + .then(b.arg("", "all")))); } - - private void safety(CommandSender sender, Command command, String label, Args args) { - if (Load.lite) { + /* Main Command Processing */ + private void processCommand(CommandSender sender, Command command, String label, Args args) { + // Lite mode check + if (Sentinel.getInstance().getDirector().loader.isLite()) { handleLiteMessage(sender, args); return; } + if (args.isEmpty()) { - sender.sendMessage(Text.prefix("Usage: /sentinel ")); + sender.sendMessage(Text.prefix(USAGE_SENTINEL)); return; } String subCommand = args.get(0).toString().toLowerCase(); switch (subCommand) { case "reload" -> handleReload(sender); + case "wand" -> handleWand(sender); case "config" -> handleConfig(sender); case "commandblock", "cb" -> handleCommandBlock(sender, args); case "debug" -> handleDebugCommand(sender, args); case "false-positive" -> handleFalsePositive(sender, args); case "socialspy" -> handleSocialSpy(sender); - default -> sender.sendMessage(Text.prefix("Invalid sub-command. Usage: /sentinel ")); + default -> sender.sendMessage(Text.prefix("Invalid sub-command. " + USAGE_SENTINEL)); } } - - private void handleReload(CommandSender sender) { + /* Helper Method: Ensure Sender is a Player */ + private Player getPlayer(CommandSender sender) { if (sender instanceof Player p) { - if (!PlayerUtils.checkPermission(sender, "sentinel.reload") || !PlayerUtils.isTrusted(p)) { - p.sendMessage(Text.prefix(Sentinel.lang.permissions.noTrust)); - return; - } + return p; } - Sentinel.log.info("Sentinel is now reloading the config."); - sender.sendMessage(Text.prefix(Sentinel.lang.plugin.reloadingConfig)); - Sentinel.getInstance().loadConfig(); + sender.sendMessage(Text.prefix("Only players can execute this command.")); + return null; } - private void handleConfig(CommandSender sender) { - if (!PlayerUtils.playerCheck(sender)) + /* ======================= + Subcommand: RELOAD + ======================= */ + private void handleReload(CommandSender sender) { + if (!PlayerUtils.isTrusted(sender)) { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.noTrust)); return; + } + Sentinel.getInstance().getLogger().info("Sentinel is now reloading the config."); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.reloadingConfig)); + Sentinel.getInstance().getDirector().io.loadConfig(); + } + + /* ======================= + Subcommand: WAND + ======================= */ + private void handleWand(CommandSender sender) { + if (!PlayerUtils.playerCheck(sender)) return; + if (!PlayerUtils.isTrusted(sender)) return; Player p = (Player) sender; - if (!PlayerUtils.checkPermission(sender, "sentinel.config") || !PlayerUtils.isTrusted(p)) - return; - if (!MainGUI.verify(p)) - return; + p.give(WandEvents.SELECTION_WAND); + sender.sendMessage(Text.prefix("Given you a selection wand.")); + } + + /* ======================= + Subcommand: CONFIG + ======================= */ + private void handleConfig(CommandSender sender) { + Player p = getPlayer(sender); + if (p == null) return; + if (!PlayerUtils.isTrusted(p)) return; + if (!MainGUI.verify(p)) return; + p.openInventory(new MainGUI().home.getInventory()); } + /* ======================= + Subcommand: COMMANDBLOCK + ======================= */ private void handleCommandBlock(CommandSender sender, Args args) { - if (!PlayerUtils.isTrusted(sender)) - return; + if (!PlayerUtils.isTrusted(sender)) return; if (args.getSize() < 2) { - sender.sendMessage(Text.prefix("Usage: /sentinel commandblock ")); + sender.sendMessage(Text.prefix(USAGE_COMMANDBLOCK)); return; } + String sub = args.get(1).toString().toLowerCase(); switch (sub) { - case "add" -> { - if (!PlayerUtils.playerCheck(sender)) - return; - Player p = (Player) sender; - Block target = p.getTargetBlock(Set.of(Material.AIR), 10); - if (target.getType() == Material.COMMAND_BLOCK || - target.getType() == Material.REPEATING_COMMAND_BLOCK || - target.getType() == Material.CHAIN_COMMAND_BLOCK) { - CommandBlock cb = (CommandBlock) target.getState(); - CBWhitelistManager.add(cb, p.getUniqueId()); - } else { - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.notCommandBlock.formatted(Text.cleanName(target.getType().toString())))); - } + case "selection" -> handleCommandBlockSelection(sender, args); + case "add" -> handleCommandBlockAdd(sender); + case "remove" -> handleCommandBlockRemove(sender); + case "auto" -> handleCommandBlockAuto(sender); + case "restore" -> handleCommandBlockRestore(sender, args); + case "clear" -> handleCommandBlockClear(sender, args); + default -> sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.invalidSubCommand.formatted("commandblock"))); + } + } + + // --- CommandBlock -> SELECTION --- + private void handleCommandBlockSelection(CommandSender sender, Args args) { + if (args.getSize() < 3) { + sender.sendMessage(Text.prefix(USAGE_SELECTION)); + return; + } + Player p = getPlayer(sender); + if (p == null) return; + + String action = args.get(2).toString().toLowerCase(); + switch (action) { + case "add" -> Sentinel.getInstance().getDirector().whitelistManager.addSelectionToWhitelist(p); + case "remove" -> Sentinel.getInstance().getDirector().whitelistManager.removeSelectionFromWhitelist(p); + case "delete" -> Sentinel.getInstance().getDirector().whitelistManager.deleteSelection(p); + case "deselect", "desel" -> WandEvents.selections.remove(p.getUniqueId()); + case "pos1" -> { + Selection selection = WandEvents.selections.computeIfAbsent(p.getUniqueId(), k -> new Selection()); + selection.setPos1(p.getLocation()); + p.sendMessage(Text.prefix("Position 1 set at " + Text.formatLoc(p.getLocation()))); } - case "remove" -> { - if (!PlayerUtils.playerCheck(sender)) - return; - Player p = (Player) sender; - Block target = p.getTargetBlock(Set.of(Material.AIR), 10); - WhitelistedBlock wb = CBWhitelistManager.get(target.getLocation()); - if (wb != null) { - CBWhitelistManager.remove(target.getLocation()); - String cleanedType = Text.cleanName(WhitelistedBlock.fromSerialized(wb.loc()).getBlock().getType().toString()); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.removeSuccess.formatted(cleanedType, wb.command()))); - } else { - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.notWhitelisted.formatted(Text.cleanName(target.getType().toString())))); - } + case "pos2" -> { + Selection selection = WandEvents.selections.computeIfAbsent(p.getUniqueId(), k -> new Selection()); + selection.setPos2(p.getLocation()); + p.sendMessage(Text.prefix("Position 2 set at " + Text.formatLoc(p.getLocation()))); } - case "auto" -> { - if (!PlayerUtils.playerCheck(sender)) - return; - Player p = (Player) sender; - if (CBWhitelistManager.autoWhitelist.contains(p.getUniqueId())) { - CBWhitelistManager.autoWhitelist.remove(p.getUniqueId()); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.autoWhitelistOn)); - } else { - CBWhitelistManager.autoWhitelist.add(p.getUniqueId()); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.autoWhitelistOff)); - } - } - case "restore" -> { - if (args.getSize() < 3) { - sender.sendMessage(Text.prefix("Usage: /sentinel commandblock restore ")); - return; - } - String targetPlayer = args.get(2).toString(); - if (targetPlayer.equalsIgnoreCase("all")) { - int result = CBWhitelistManager.restoreAll(); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.restoreSuccess.formatted(result))); - } else { - UUID id = Bukkit.getOfflinePlayer(targetPlayer).getUniqueId(); - int result = CBWhitelistManager.restoreAll(id); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.restorePlayerSuccess.formatted(result,targetPlayer))); - } - } - case "clear" -> { - if (args.getSize() < 3) { - sender.sendMessage(Text.prefix("Usage: /sentinel commandblock clear ")); - return; - } - String targetPlayer = args.get(2).toString(); - if (targetPlayer.equalsIgnoreCase("all")) { - int result = CBWhitelistManager.clearAll(); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.clearSuccess.formatted(result))); - } else { - UUID id = Bukkit.getOfflinePlayer(targetPlayer).getUniqueId(); - int result = CBWhitelistManager.clearAll(id); - sender.sendMessage(Text.prefix(Sentinel.lang.commandBlock.clearPlayerSuccess.formatted(result,targetPlayer))); - } - } - default -> sender.sendMessage(Text.prefix(Sentinel.lang.plugin.invalidSubCommand.formatted("commandblock"))); + default -> p.sendMessage(Text.prefix("Invalid selection action. " + USAGE_SELECTION)); } } - private void handleDebugCommand(CommandSender sender, Args args) { - if (!PlayerUtils.checkPermission(sender, "sentinel.debug")) + // --- CommandBlock -> ADD --- + private void handleCommandBlockAdd(CommandSender sender) { + Player p = getPlayer(sender); + if (p == null) return; + + if (p.getTargetEntity(10) instanceof CommandMinecart cm) { + Sentinel.getInstance().getDirector().whitelistManager + .generateHolder(p.getUniqueId(), cm).addToWhitelist(); return; + } + Block target = p.getTargetBlock(Set.of(Material.AIR), 10); + if (ServerUtils.isCommandBlock(target)) { + CommandBlock cb = (CommandBlock) target.getState(); + Sentinel.getInstance().getDirector().whitelistManager + .generateHolder(p.getUniqueId(), cb).addToWhitelist(); + } else { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.notCommandBlock + .formatted(Text.cleanName(target.getType().toString())))); + } + } + + // --- CommandBlock -> REMOVE --- + private void handleCommandBlockRemove(CommandSender sender) { + Player p = getPlayer(sender); + if (p == null) return; + + if (p.getTargetEntity(10) instanceof CommandMinecart cm) { + CommandBlockHolder wb = Sentinel.getInstance().getDirector().whitelistManager + .generateHolder(p.getUniqueId(), cm); + if (wb.removeFromWhitelist()) { + String cleanedType = Text.cleanName(SerialLocation.translate(wb.loc()).getBlock().getType().toString()); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.removeSuccess + .formatted(cleanedType, wb.command()))); + } else { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.notWhitelisted + .formatted(Text.cleanName(cm.getType().toString())))); + } + return; + } + + Block target = p.getTargetBlock(Set.of(Material.AIR), 10); + CommandBlockHolder wb = Sentinel.getInstance().getDirector().whitelistManager + .getFromWhitelist(target.getLocation()); + if (wb != null && wb.removeFromWhitelist()) { + String cleanedType = Text.cleanName(SerialLocation.translate(wb.loc()).getBlock().getType().toString()); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.removeSuccess + .formatted(cleanedType, wb.command()))); + } else { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.notWhitelisted + .formatted(Text.cleanName(target.getType().toString())))); + } + } + + // --- CommandBlock -> AUTO --- + private void handleCommandBlockAuto(CommandSender sender) { + Player p = getPlayer(sender); + if (p == null) return; + + var whitelistManager = Sentinel.getInstance().getDirector().whitelistManager; + if (whitelistManager.autoWhitelist.contains(p.getUniqueId())) { + whitelistManager.autoWhitelist.remove(p.getUniqueId()); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.autoWhitelistOn)); + } else { + whitelistManager.autoWhitelist.add(p.getUniqueId()); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.autoWhitelistOff)); + } + } + + // --- CommandBlock -> RESTORE --- + private void handleCommandBlockRestore(CommandSender sender, Args args) { + if (args.getSize() < 3) { + sender.sendMessage(Text.prefix(USAGE_RESTORE)); + return; + } + String targetPlayer = args.get(2).toString(); + if (targetPlayer.equalsIgnoreCase("all")) { + int result = Sentinel.getInstance().getDirector().whitelistManager.restoreAll(); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.restoreSuccess + .formatted(result))); + } else { + UUID id = Bukkit.getOfflinePlayer(targetPlayer).getUniqueId(); + int result = Sentinel.getInstance().getDirector().whitelistManager.restoreAll(id); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.restorePlayerSuccess + .formatted(result, targetPlayer))); + } + } + + // --- CommandBlock -> CLEAR --- + private void handleCommandBlockClear(CommandSender sender, Args args) { + if (args.getSize() < 3) { + sender.sendMessage(Text.prefix(USAGE_CLEAR)); + return; + } + String targetPlayer = args.get(2).toString(); + if (targetPlayer.equalsIgnoreCase("all")) { + int result = Sentinel.getInstance().getDirector().whitelistManager.clearAll(); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.clearSuccess + .formatted(result))); + } else { + UUID id = Bukkit.getOfflinePlayer(targetPlayer).getUniqueId(); + int result = Sentinel.getInstance().getDirector().whitelistManager.clearAll(id); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.commandBlock.clearPlayerSuccess + .formatted(result, targetPlayer))); + } + } + + /* ======================= + Subcommand: DEBUG + ======================= */ + private void handleDebugCommand(CommandSender sender, Args args) { + if (!PlayerUtils.checkPermission(sender, "sentinel.debug")) return; if (args.getSize() < 2) { sender.sendMessage(Text.prefix("Usage: /sentinel debug ")); return; } String sub = args.get(1).toString().toLowerCase(); switch (sub) { - case "lang" -> sender.sendMessage(Sentinel.lang.brokenLang); + case "lang" -> sender.sendMessage(Sentinel.getInstance().getDirector().io.lang.brokenLang); case "toggle" -> { - Sentinel.mainConfig.debugMode = !Sentinel.mainConfig.debugMode; - String message = Sentinel.mainConfig.debugMode - ? Sentinel.lang.debug.debugEnabled - : Sentinel.lang.debug.debugDisabled; + Sentinel.getInstance().getDirector().io.mainConfig.debugMode = !Sentinel.getInstance().getDirector().io.mainConfig.debugMode; + String message = Sentinel.getInstance().getDirector().io.mainConfig.debugMode + ? Sentinel.getInstance().getDirector().io.lang.debug.debugEnabled + : Sentinel.getInstance().getDirector().io.lang.debug.debugDisabled; sender.sendMessage(Text.prefix(message)); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); } - case "chat" -> { - if (!PlayerUtils.playerCheck(sender)) - return; - if (args.getSize() < 3) { - sender.sendMessage(Text.prefix("Usage: /sentinel debug chat ")); - return; - } - Player p = (Player) sender; - String messageText = args.getAll(2).toString(); - AsyncChatEvent message = new AsyncChatEvent(true, - p, - Set.of(p), - ChatRenderer.defaultRenderer(), - Component.text(messageText), - Component.text(messageText), - SignedMessage.system(messageText, Component.text(messageText)) - ); - UnicodeFilter.handleUnicodeFilter(message); - UrlFilter.handleUrlFilter(message); - SpamFilter.handleSpamFilter(message); - ProfanityFilter.handleProfanityFilter(message); - if (!message.isCancelled()) { - sender.sendMessage(Text.prefix(Sentinel.lang.debug.notFlagged)); - } - } - default -> sender.sendMessage(Text.prefix(Sentinel.lang.plugin.invalidSubCommand.formatted("debug"))); + case "chat" -> handleDebugChat(sender, args); + default -> sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.invalidSubCommand.formatted("debug"))); } } + private void handleDebugChat(CommandSender sender, Args args) { + if (!PlayerUtils.playerCheck(sender)) return; + if (args.getSize() < 3) { + sender.sendMessage(Text.prefix("Usage: /sentinel debug chat ")); + return; + } + Player p = (Player) sender; + String messageText = args.getAll(2).toString(); + AsyncChatEvent chatEvent = new AsyncChatEvent(true, + p, + Set.of(p), + ChatRenderer.defaultRenderer(), + Component.text(messageText), + Component.text(messageText), + SignedMessage.system(messageText, Component.text(messageText)) + ); + UnicodeFilter.handleUnicodeFilter(chatEvent); + UrlFilter.handleUrlFilter(chatEvent); + SpamFilter.handleSpamFilter(chatEvent); + ProfanityFilter.handleProfanityFilter(chatEvent); + if (!chatEvent.isCancelled()) { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.debug.notFlagged)); + } + } + + /* ======================= + Subcommand: FALSE-POSITIVE + ======================= */ private void handleFalsePositive(CommandSender sender, Args args) { if (args.getSize() < 2) { sender.sendMessage(Text.prefix("Usage: /sentinel false-positive ")); return; } - if (!PlayerUtils.checkPermission(sender, "sentinel.false-positive")) - return; + if (!PlayerUtils.checkPermission(sender, "sentinel.false-positive")) return; String sub = args.get(1).toString().toLowerCase(); String falsePositive = args.getAll(2).toString(); + Node root = new Node("Sentinel"); root.addTextLine("False Positive Management Log"); Node info = new Node("Info"); info.addKeyValue("User", sender.getName()); + switch (sub) { case "add" -> { - if (!PlayerUtils.checkPermission(sender,"sentinel.false-positive.add")) return; - Sentinel.fpConfig.swearWhitelist.add(falsePositive); - sender.sendMessage(Text.prefix(Sentinel.lang.falsePositive.addSuccess.formatted(falsePositive))); + if (!PlayerUtils.checkPermission(sender, "sentinel.false-positive.add")) return; + Sentinel.getInstance().getDirector().io.fpConfig.swearWhitelist.add(falsePositive); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.falsePositive.addSuccess.formatted(falsePositive))); info.addKeyValue("Action", "Add"); } case "remove" -> { - if (!PlayerUtils.checkPermission(sender,"sentinel.false-positive.remove")) return; - Sentinel.fpConfig.swearWhitelist.remove(falsePositive); - sender.sendMessage(Text.prefix(Sentinel.lang.falsePositive.removeSuccess.formatted(falsePositive))); + if (!PlayerUtils.checkPermission(sender, "sentinel.false-positive.remove")) return; + Sentinel.getInstance().getDirector().io.fpConfig.swearWhitelist.remove(falsePositive); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.falsePositive.removeSuccess.formatted(falsePositive))); info.addKeyValue("Action", "Remove"); } default -> { - sender.sendMessage(Text.prefix(Sentinel.lang.plugin.invalidSubCommand.formatted("false-positive"))); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.invalidSubCommand.formatted("false-positive"))); return; } } info.addKeyValue("False Positive Edited", falsePositive); root.addChild(info); - Sentinel.fpConfig.save(); - Sentinel.log.info(ConsoleFormatter.format(root)); + Sentinel.getInstance().getDirector().io.fpConfig.save(); + Sentinel.getInstance().getLogger().info(ConsoleFormatter.format(root)); EmbedFormatter.sendEmbed(EmbedFormatter.format(root)); } + /* ======================= + Subcommand: SOCIALSPY + ======================= */ private void handleSocialSpy(CommandSender sender) { - if (!PlayerUtils.playerCheck(sender)) - return; - if (!PlayerUtils.checkPermission(sender, "sentinel.socialspy")) - return; + if (!PlayerUtils.playerCheck(sender)) return; + if (!PlayerUtils.checkPermission(sender, "sentinel.socialspy")) return; Player p = (Player) sender; UUID senderID = p.getUniqueId(); boolean enabled = spyMap.getOrDefault(senderID, false); if (!enabled) { - sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.enabled)); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.socialSpy.enabled)); spyMap.put(senderID, true); } else { - sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.disabled)); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.socialSpy.disabled)); spyMap.put(senderID, false); } } + /* ======================= + Lite Mode Handler + ======================= */ private void handleLiteMessage(CommandSender sender, Args args) { if (!args.isEmpty() && args.get(0).toString().equalsIgnoreCase("reload")) { - if (sender instanceof Player p && !PlayerUtils.isTrusted(p)) { - sender.sendMessage(Text.prefix(Sentinel.lang.permissions.noTrust)); + if (!PlayerUtils.isTrusted(sender)) { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.noTrust)); return; } - Sentinel.log.info("Sentinel is now reloading the config in lite mode."); - sender.sendMessage(Text.prefix(Sentinel.lang.plugin.reloadingConfigLite)); - Sentinel.getInstance().loadConfig(); + Sentinel.getInstance().getLogger().info("Sentinel is now reloading the config in lite mode."); + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.plugin.reloadingConfigLite)); + Sentinel.getInstance().getDirector().io.loadConfig(); - if (Load.load(Sentinel.getInstance().license, Sentinel.getInstance().identifier, false)) { + if (Sentinel.getInstance().getDirector().loader.load(Sentinel.getInstance().license, Sentinel.getInstance().identifier, false)) { return; } - Sentinel.log.info("Re-authentication Failed."); + Sentinel.getInstance().getLogger().info("Re-authentication Failed."); } else { - sender.sendMessage(Load.liteMode); + sender.sendMessage(Loader.LITE_MODE); } } -} +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/commands/TrapCommand.java b/src/main/java/me/trouper/sentinel/server/commands/TrapCommand.java index 196c584..e4f59fa 100644 --- a/src/main/java/me/trouper/sentinel/server/commands/TrapCommand.java +++ b/src/main/java/me/trouper/sentinel/server/commands/TrapCommand.java @@ -23,7 +23,6 @@ public class TrapCommand implements CustomCommand { @Override public void dispatchCompletions(CommandSender commandSender, Command command, String s, CompletionBuilder b) { - ServerUtils.verbose("Listing the fake plugins: %s".formatted(Sentinel.advConfig.fakePlugins)); - b.then(b.arg(Sentinel.advConfig.fakePlugins)); + b.then(b.arg(Sentinel.getInstance().getDirector().io.advConfig.fakePlugins)); } } diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockEdit.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockEdit.java deleted file mode 100644 index d30bb1a..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockEdit.java +++ /dev/null @@ -1,56 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.trees.Node; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.block.CommandBlock; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.entity.EntityChangeBlockEvent; - -public class CommandBlockEdit extends AbstractViolation { - - @EventHandler - private void onCMDBlockChange(EntityChangeBlockEvent e) { - //ServerUtils.verbose("CommandBlockChange: Detected the event"); - if (!Sentinel.violationConfig.commandBlockEdit.enabled) return; - //ServerUtils.verbose("CommandBlockChange: Enabled"); - if (!(e.getEntity() instanceof Player p)) return; - //ServerUtils.verbose("CommandBlockChange: Changer is a player"); - Block b = e.getBlock(); - if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) - return; - ServerUtils.verbose("CommandBlockChange: Block is a command block"); - CommandBlock cb = (CommandBlock) b.getState(); - if (PlayerUtils.isTrusted(p)) { - if (!CBWhitelistManager.autoWhitelist.contains(p.getUniqueId())) return; - CBWhitelistManager.add(cb, p.getUniqueId()); - return; - } - ServerUtils.verbose("CommandBlockChange: Not trusted, performing action"); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .deop(Sentinel.violationConfig.commandBlockEdit.deop) - .cancel(true) - .punish(Sentinel.violationConfig.commandBlockEdit.punish) - .setPunishmentCommands(Sentinel.violationConfig.commandBlockEdit.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandBlockEdit.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.edit, Sentinel.lang.violations.protections.rootName.commandBlock), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.edit, Sentinel.lang.violations.protections.rootName.commandBlock), - generateCommandBlockInfo(cb), - config - ); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockExecute.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockExecute.java deleted file mode 100644 index 5d4a391..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockExecute.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.CommandBlock; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.event.EventHandler; -import org.bukkit.event.server.ServerCommandEvent; - -public class CommandBlockExecute extends AbstractViolation { - - @EventHandler - private void commandBlockExecute(ServerCommandEvent e) { - //ServerUtils.verbose("Handling command block event: " + e.getCommand()); - if (!Sentinel.violationConfig.commandBlockExecute.enabled) return; - //ServerUtils.verbose("Whitelist not disabled "); - if (!(e.getSender() instanceof BlockCommandSender s)) return; - //ServerUtils.verbose("Sender is command block"); - Block cmdBlock = s.getBlock(); - if (CBWhitelistManager.canRun(cmdBlock)) return; - ServerUtils.verbose("Command block can't run."); - - CommandBlock cb = (CommandBlock) cmdBlock.getState(); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setBlock(cmdBlock) - .cancel(true) - .destroyBlock(Sentinel.violationConfig.commandBlockExecute.destroyBlock) - .restoreBlock(Sentinel.violationConfig.commandBlockExecute.attemptRestore) - .logToDiscord(Sentinel.violationConfig.commandBlockExecute.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.lang.violations.protections.rootName.commandBlockWhitelist), - Sentinel.lang.violations.protections.rootName.rootNameFormat.formatted( Sentinel.lang.violations.protections.rootName.commandBlockWhitelist), - generateCommandBlockInfo(cb), - config - ); - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartPlace.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartPlace.java deleted file mode 100644 index 35dc6f9..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartPlace.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerInteractEvent; - -public class CommandBlockMinecartPlace extends AbstractViolation { - - @EventHandler - private void onCMDMinecartPlace(PlayerInteractEvent e) { - //ServerUtils.verbose("MinecartCommandPlace: Detected interaction"); - if (!Sentinel.violationConfig.commandBlockMinecartPlace.enabled) return; - //ServerUtils.verbose("MinecartCommandPlace: Check is enabled"); - Player p = e.getPlayer(); - if (!p.isOp()) return; - //ServerUtils.verbose("MinecartCommandPlace: Player is op"); - if (e.getItem() == null) return; - ServerUtils.verbose("MinecartCommandPlace: Item isn't null"); - if (e.getClickedBlock() == null) return; - ServerUtils.verbose("MinecartCommandPlace: Clicked block isn't null"); - if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return; - ServerUtils.verbose("MinecartCommandPlace: Item is a minecart command"); - if (!(e.getClickedBlock().getType() == Material.RAIL || e.getClickedBlock().getType() == Material.POWERED_RAIL || e.getClickedBlock().getType() == Material.ACTIVATOR_RAIL || e.getClickedBlock().getType() == Material.DETECTOR_RAIL)) return; - ServerUtils.verbose("MinecartCommandPlace: Clicked block is a rail"); - if (PlayerUtils.isTrusted(p)) return; - ServerUtils.verbose("MinecartCommandPlace: Not trusted, performing action"); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .cancel(true) - .punish(Sentinel.violationConfig.commandBlockMinecartPlace.punish) - .deop(Sentinel.violationConfig.commandBlockMinecartPlace.deop) - .setPunishmentCommands(Sentinel.violationConfig.commandBlockMinecartPlace.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandBlockMinecartPlace.logToDiscord); - - // Remove the command block minecart from the player's inventory - p.getInventory().remove(Material.COMMAND_BLOCK_MINECART); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.place, Sentinel.lang.violations.protections.rootName.minecartCommandBlock), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.place, Sentinel.lang.violations.protections.rootName.minecartCommandBlock), - generateBlockInfo(e.getClickedBlock()), - config - ); - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartUse.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartUse.java deleted file mode 100644 index 182f596..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockMinecartUse.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerInteractEntityEvent; - -public class CommandBlockMinecartUse extends AbstractViolation { - - @EventHandler - private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) { - //ServerUtils.verbose("MinecartCommandUse: Detected Interaction with entity"); - if (!Sentinel.violationConfig.commandBlockMinecartUse.enabled) return; - //ServerUtils.verbose("MinecartCommandUse: Enabled"); - Player p = e.getPlayer(); - if (!p.isOp()) return; - ServerUtils.verbose("MinecartCommandUse: Player op"); - if (e.getRightClicked().getType() != EntityType.COMMAND_BLOCK_MINECART) return; - ServerUtils.verbose("MinecartCommandUse: Entity is minecart command"); - if (PlayerUtils.isTrusted(p)) return; - ServerUtils.verbose("MinecartCommandUse: Not trusted, performing action"); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .cancel(true) - .punish(Sentinel.violationConfig.commandBlockMinecartUse.punish) - .deop(Sentinel.violationConfig.commandBlockMinecartUse.deop) - .setPunishmentCommands(Sentinel.violationConfig.commandBlockMinecartUse.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandBlockMinecartUse.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.use, Sentinel.lang.violations.protections.rootName.minecartCommandBlock), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.use, Sentinel.lang.violations.protections.rootName.minecartCommandBlock), - generateMinecartInfo(e.getRightClicked()), - config - ); - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockPlace.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockPlace.java deleted file mode 100644 index 12a2f1c..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockPlace.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.CommandBlock; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.block.BlockPlaceEvent; - -public class CommandBlockPlace extends AbstractViolation { - - @EventHandler - public void listen(BlockPlaceEvent e) { - //ServerUtils.verbose("CommandBlockPlace: Detected block place"); - if (!Sentinel.violationConfig.commandBlockPlace.enabled) return; - //ServerUtils.verbose("CommandBlockPlace: Enabled"); - Player p = e.getPlayer(); - if (!p.isOp()) return; - //ServerUtils.verbose("CommandBlockPlace: Player is operator"); - Block b = e.getBlockPlaced(); - if (!(b.getType().equals(Material.COMMAND_BLOCK) || - b.getType().equals(Material.REPEATING_COMMAND_BLOCK) || - b.getType().equals(Material.CHAIN_COMMAND_BLOCK))) return; - ServerUtils.verbose("CommandBlockPlace: Block is a command block"); - CommandBlock cb = (CommandBlock) b.getState(); - if (PlayerUtils.isTrusted(p)) return; - ServerUtils.verbose("CommandBlockPlace: Not trusted, performing action"); - - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .deop(Sentinel.violationConfig.commandBlockPlace.deop) - .cancel(true) - .setEvent(e) - .punish(true) - .setPunishmentCommands(Sentinel.violationConfig.commandBlockPlace.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandBlockPlace.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.place, Sentinel.lang.violations.protections.rootName.commandBlock), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.place, Sentinel.lang.violations.protections.rootName.commandBlock), - generateCommandBlockInfo(cb), - config - ); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandBlockUse.java b/src/main/java/me/trouper/sentinel/server/events/CommandBlockUse.java deleted file mode 100644 index 978e3fe..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandBlockUse.java +++ /dev/null @@ -1,58 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.CommandBlock; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerInteractEvent; - -public class CommandBlockUse extends AbstractViolation { - - @EventHandler - private void onCMDBlockUse(PlayerInteractEvent e) { - //ServerUtils.verbose("CommandBlockUse: Detected Interaction"); - if (!Sentinel.violationConfig.commandBlockUse.enabled) return; - //ServerUtils.verbose("CommandBlockUse: Enabled"); - Player p = e.getPlayer(); - if (!p.isOp()) return; - //ServerUtils.verbose("CommandBlockUse: Player is op"); - if (e.getClickedBlock() == null) return; - //ServerUtils.verbose("CommandBlockUse: Block isn't null"); - Block b = e.getClickedBlock(); - if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return; - CommandBlock cb = (CommandBlock) b.getState(); - ServerUtils.verbose("CommandBlockUse: Block is a command block"); - if (PlayerUtils.isTrusted(p)) { - if (!CBWhitelistManager.autoWhitelist.contains(p.getUniqueId())) return; - if (CBWhitelistManager.canRun(cb.getBlock())) return; - e.setCancelled(true); - CBWhitelistManager.add(cb, p.getUniqueId()); - return; - } - ServerUtils.verbose("CommandBlockUse: Not trusted, performing action"); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .deop(Sentinel.violationConfig.commandBlockUse.deop) - .cancel(true) - .punish(Sentinel.violationConfig.commandBlockUse.punish) - .setPunishmentCommands(Sentinel.violationConfig.commandBlockUse.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandBlockUse.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.use, Sentinel.lang.violations.protections.rootName.commandBlock), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.use, Sentinel.lang.violations.protections.rootName.commandBlock), - generateCommandBlockInfo(cb), - config - ); - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/CommandExecute.java b/src/main/java/me/trouper/sentinel/server/events/CommandExecute.java deleted file mode 100644 index c7ac7ad..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CommandExecute.java +++ /dev/null @@ -1,101 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.utils.PlayerUtils; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; - -import java.util.HashSet; -import java.util.Set; - -public class CommandExecute extends AbstractViolation { - - @EventHandler - private void onCommand(PlayerCommandPreprocessEvent e) { - Player p = e.getPlayer(); - if (PlayerUtils.isTrusted(p)) return; - String label = e.getMessage().substring(1).split(" ")[0]; - String args = e.getMessage(); - - Set status = getCommandStatus(label); - - if (status.contains("SPECIFIC") && Sentinel.violationConfig.commandExecute.specific.enabled) { - e.setCancelled(true); - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .cancel(true) - .punish(Sentinel.violationConfig.commandExecute.specific.punish) - .setPunishmentCommands(Sentinel.violationConfig.commandExecute.specific.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandExecute.specific.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.specificCommand), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.specificCommand), - generateCommandInfo(args, p), - config - ); - return; - } - - if (status.contains("DANGEROUS") && Sentinel.violationConfig.commandExecute.dangerous.enabled) { - e.setCancelled(true); - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .deop(Sentinel.violationConfig.commandExecute.dangerous.deop) - .cancel(true) - .punish(Sentinel.violationConfig.commandExecute.dangerous.punish) - .setPunishmentCommands(Sentinel.violationConfig.commandExecute.dangerous.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.commandExecute.dangerous.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.dangerousCommand), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.dangerousCommand), - generateCommandInfo(args, p), - config - ); - return; - } - - if (status.contains("LOGGED") && Sentinel.violationConfig.commandExecute.logged.enabled) { - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setPlayer(p) - .logToDiscord(Sentinel.violationConfig.commandExecute.logged.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.loggedCommand), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.run, Sentinel.lang.violations.protections.rootName.loggedCommand), - generateCommandInfo(args, p), - config - ); - return; - } - } - - public static Set getCommandStatus(String label) { - Set commandTypes = new HashSet<>(); - - if (label.startsWith("/")) { - label = label.substring(1); - } - - if (label.contains(":")) { - commandTypes.add("SPECIFIC"); - } - - for (String loggedCommand : Sentinel.violationConfig.commandExecute.logged.commands) { - if (loggedCommand.equals(label)) commandTypes.add("LOGGED"); - } - - for (String dangerousCommand : Sentinel.violationConfig.commandExecute.dangerous.commands) { - if (dangerousCommand.equals(label)) commandTypes.add("DANGEROUS"); - } - - return commandTypes; - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/CreativeHotbar.java b/src/main/java/me/trouper/sentinel/server/events/CreativeHotbar.java deleted file mode 100644 index edfd979..0000000 --- a/src/main/java/me/trouper/sentinel/server/events/CreativeHotbar.java +++ /dev/null @@ -1,52 +0,0 @@ -package me.trouper.sentinel.server.events; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.AbstractViolation; -import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; -import me.trouper.sentinel.utils.ItemUtils; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.inventory.InventoryCreativeEvent; -import org.bukkit.inventory.ItemStack; - -public class CreativeHotbar extends AbstractViolation { - - @EventHandler - private void onNBTPull(InventoryCreativeEvent e) { - //ServerUtils.verbose("NBT: Detected creative mode action"); - if (!Sentinel.violationConfig.creativeHotbarAction.enabled) return; - ServerUtils.verbose("NBT: Enabled"); - if (!(e.getWhoClicked() instanceof Player p)) return; - ServerUtils.verbose("NBT: Clicker is a player"); - if (e.getCursor() == null) return; // Well it threw an exception during testing, so it isn't always false! - ServerUtils.verbose("NBT: Cursor isn't null"); - ItemStack i = e.getCursor(); - if (PlayerUtils.isTrusted(p)) return; - ServerUtils.verbose("NBT: Not trusted"); - if (e.getCursor().getItemMeta() == null) return; - ServerUtils.verbose("NBT: Cursor has meta"); - if (!(i.hasItemMeta() && i.getItemMeta() != null)) return; - ServerUtils.verbose("NBT: Item has meta"); - if (ItemUtils.itemPasses(i)) return; - ServerUtils.verbose("NBT: Item doesn't pass, performing action"); - - ActionConfiguration.Builder config = new ActionConfiguration.Builder() - .setEvent(e) - .setPlayer(p) - .cancel(true) - .punish(Sentinel.violationConfig.creativeHotbarAction.punish) - .deop(Sentinel.violationConfig.creativeHotbarAction.deop) - .setPunishmentCommands(Sentinel.violationConfig.creativeHotbarAction.punishmentCommands) - .logToDiscord(Sentinel.violationConfig.creativeHotbarAction.logToDiscord); - - runActions( - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.grab, Sentinel.lang.violations.protections.rootName.nbtItem), - Sentinel.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.lang.violations.protections.rootName.grab, Sentinel.lang.violations.protections.rootName.nbtItem), - generateItemInfo(i), - config - ); - } -} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/admin/AntiBanEvents.java b/src/main/java/me/trouper/sentinel/server/events/admin/AntiBanEvents.java new file mode 100644 index 0000000..1bdc40e --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/admin/AntiBanEvents.java @@ -0,0 +1,29 @@ +package me.trouper.sentinel.server.events.admin; + +import io.github.itzispyder.pdk.events.CustomListener; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.PlayerUtils; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerLoginEvent; + +public class AntiBanEvents implements CustomListener { + + // Well. I hope that no banning plugins use the highest priority as well, that would be embarrassing. + @EventHandler(priority = EventPriority.HIGHEST) + public void onKick(PlayerKickEvent e) { + if (PlayerUtils.isTrusted(e.getPlayer()) && Sentinel.getInstance().getDirector().io.mainConfig.plugin.antiBan) e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onLogin(PlayerLoginEvent e) { + if (PlayerUtils.isTrusted(e.getPlayer()) && Sentinel.getInstance().getDirector().io.mainConfig.plugin.antiBan) e.allow(); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void beforeLogin(AsyncPlayerPreLoginEvent e) { + if (PlayerUtils.isTrusted(e.getUniqueId()) && Sentinel.getInstance().getDirector().io.mainConfig.plugin.antiBan) e.allow(); + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/admin/BlockDisplayHideEvent.java b/src/main/java/me/trouper/sentinel/server/events/admin/BlockDisplayHideEvent.java new file mode 100644 index 0000000..35192d1 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/admin/BlockDisplayHideEvent.java @@ -0,0 +1,23 @@ +package me.trouper.sentinel.server.events.admin; + +import io.github.itzispyder.pdk.events.CustomListener; +import me.trouper.sentinel.Sentinel; +import org.bukkit.entity.BlockDisplay; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; + +public class BlockDisplayHideEvent implements CustomListener { + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + for (Entity entity : player.getWorld().getEntities()) { + if (entity instanceof BlockDisplay && entity.getScoreboardTags().contains("./Sentinel/ Block Display")) { + player.hideEntity(Sentinel.getInstance(), entity); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/admin/WandEvents.java b/src/main/java/me/trouper/sentinel/server/events/admin/WandEvents.java new file mode 100644 index 0000000..c82807a --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/admin/WandEvents.java @@ -0,0 +1,278 @@ +package me.trouper.sentinel.server.events.admin; + +import io.github.itzispyder.pdk.events.CustomListener; +import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; +import io.github.itzispyder.pdk.utils.misc.SoundPlayer; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.data.types.Selection; +import me.trouper.sentinel.utils.DisplayUtils; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import me.trouper.sentinel.utils.display.BlockDisplayRaytracer; +import org.bukkit.*; +import org.bukkit.block.CommandBlock; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.vehicle.VehicleDamageEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class WandEvents implements CustomListener { + public static final ItemStack SELECTION_WAND = ItemBuilder.create() + .material(Material.BLAZE_ROD) + .name(Text.color("&dCommand Block Wand")) + .lore(Text.color("&7Use this wand to manage command blocks.")) + .lore(Text.color("&7It can scan up to 10 blocks away.")) + .lore(Text.color("&7Selections are visible up to 64 blocks away.")) + .lore(Text.color("&8&l➥&r &7Left Click&8:&f Set Position 1")) + .lore(Text.color("&8&l➥&r &7Right Click&8:&f Set Position 2")) + .lore(Text.color("&8&l➥&r &7Break CMD Block&8:&f Remove from whitelist")) + .lore(Text.color("&8&l➥&r &7Click CMD Block&8:&f Add to whitelist")) + .lore(Text.color("&8&l➥&r &7Sneak&8:&f Force Position Setting")) + .lore(Text.color("&7Blocks close to you will get highlighted when holding.")) + .lore(Text.color(" &fHighlight Color Key&8:")) + .lore(Text.color(" &8- &cRed &7: &fNot whitelisted.")) + .lore(Text.color(" &8- &aGreen &7: &fWhitelisted.")) + .lore(Text.color(" &8- &9Blue &7: &fYour selection.")) + .lore(Text.color(" &8- &dPurple &7: &fMissing Command Block")) + .lore(Text.color(" &8- &fBlack &7: &fUnknown Command Block (Auto-Correcting)")) + .customModelData(1984) + .build(); + + public static final Map selections = new HashMap<>(); + private static final ConcurrentLinkedQueue blockHighlights = new ConcurrentLinkedQueue<>(); + private static final Map> playerBlockHighlights = new ConcurrentHashMap<>(); + private static final ConcurrentLinkedQueue entityHighlights = new ConcurrentLinkedQueue<>(); + private static final Map> playerEntityHighlights = new ConcurrentHashMap<>(); + + @EventHandler + public void onClickEntity(PlayerInteractEntityEvent e) { + Player p = e.getPlayer(); + ItemStack i = p.getInventory().getItemInMainHand(); + + if (!i.isSimilar(SELECTION_WAND)) return; + if (!PlayerUtils.isTrusted(p)) return; + + SoundPlayer add = new SoundPlayer(p.getLocation(),Sound.ENTITY_EXPERIENCE_ORB_PICKUP,100,1); + if (!(e.getRightClicked() instanceof CommandMinecart cm)) return; + + e.setCancelled(true); + + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cm).addToWhitelist(); + add.play(p); + } + + @EventHandler + public void onDamage(VehicleDamageEvent e) { + if (!(e.getAttacker() instanceof Player p)) return; + ItemStack i = p.getInventory().getItemInMainHand(); + + if (!i.isSimilar(SELECTION_WAND)) return; + if (!PlayerUtils.isTrusted(p)) return; + + SoundPlayer remove = new SoundPlayer(p.getLocation(),Sound.BLOCK_GLASS_BREAK,100,1); + + if (!(e.getVehicle() instanceof CommandMinecart cm)) return; + e.setCancelled(true); + + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cm).removeFromWhitelist(); + remove.play(p); + } + + @EventHandler + public void onClick(PlayerInteractEvent e) { + Player p = e.getPlayer(); + ItemStack i = p.getInventory().getItemInMainHand(); + + if (!i.isSimilar(SELECTION_WAND)) return; + if (!PlayerUtils.isTrusted(p)) return; + + SoundPlayer add = new SoundPlayer(p.getLocation(),Sound.ENTITY_EXPERIENCE_ORB_PICKUP,100,1); + SoundPlayer remove = new SoundPlayer(p.getLocation(),Sound.BLOCK_GLASS_BREAK,100,1); + SoundPlayer set1 = new SoundPlayer(p.getLocation(),Sound.UI_BUTTON_CLICK,100,1); + SoundPlayer set2 = new SoundPlayer(p.getLocation(),Sound.UI_BUTTON_CLICK,100,0.8F); + + Selection selection = selections.computeIfAbsent(p.getUniqueId(), k -> new Selection()); + if (p.getTargetBlockExact(10) == null) return; + Location loc = p.getTargetBlockExact(10).getLocation(); + + if (e.getAction() == Action.LEFT_CLICK_BLOCK) { + e.setCancelled(true); + if (p.isSneaking() && ServerUtils.isCommandBlock(loc.getBlock())) { + set1.play(p); + setPos1(p,selection,loc); + } else if (ServerUtils.isCommandBlock(loc.getBlock())) { + remove.play(p); + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),(CommandBlock) loc.getBlock().getState()).removeFromWhitelist(); + } else { + set1.play(p); + setPos1(p,selection,loc); + } + } else if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { + e.setCancelled(true); + if (p.isSneaking() && ServerUtils.isCommandBlock(loc.getBlock())) { + set2.play(p); + setPos2(p,selection,loc); + } else if (ServerUtils.isCommandBlock(loc.getBlock())) { + add.play(p); + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),(CommandBlock) loc.getBlock().getState()).addToWhitelist(); + } else { + set2.play(p); + setPos2(p,selection,loc); + } + } + } + + private record EntityHighlight(Player beholder, Entity ent, Color color) { + public void display() { + for (int i = 0; i < 5; i++) { + DisplayUtils.ring(ent.getLocation().clone().add(0, (double) i /5,0),0.6, (location) -> { + DisplayUtils.PLAYER_DUST_PARTICLE_FACTORY.apply(color,1F).accept(beholder,location); + },((location, integer) -> { + return integer % 36 == 0; + })); + } + } + } + + private record BlockHighlight(Player beholder, Location loc, Material color) { + public void display() { + BlockDisplayRaytracer.outline(color, loc, 0.05, 2, List.of(beholder)); + } + } + + private static void sortNear(Player p) { + ItemStack i = p.getInventory().getItemInMainHand(); + + if (!i.isSimilar(SELECTION_WAND) || !PlayerUtils.isTrusted(p)) { + Set existingBlocks = playerBlockHighlights.remove(p.getUniqueId()); + Set existingEntities = playerEntityHighlights.remove(p.getUniqueId()); + if (existingBlocks != null) { + blockHighlights.removeAll(existingBlocks); + entityHighlights.removeAll(existingEntities); + } + return; + } + + Set currentBlocks = new HashSet<>(); + Set currentEntities = new HashSet<>(); + Selection around = new Selection(); + around.setPos1(p.getLocation().add(-10, -10, -10)); + around.setPos2(p.getLocation().add(10, 10, 10)); + around.getBlocks().stream() + .filter(block -> ServerUtils.isCommandBlock(block) && block.getLocation().distance(p.getLocation()) <= 10) + .forEach(block -> { + CommandBlock cb = (CommandBlock) block.getState(); + CommandBlockHolder holder = Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cb); + Material color = holder.isWhitelisted() + ? Material.LIME_CONCRETE_POWDER + : Material.RED_CONCRETE_POWDER; + if (holder.isUnknown()) { + color = Material.BLACK_CONCRETE_POWDER; + holder.addToExisting(); + } + currentBlocks.add(new BlockHighlight(p, block.getLocation(), color)); + }); + + List carts = p.getNearbyEntities(10,10,10).stream().filter(entity -> entity instanceof CommandMinecart).toList(); + + for (Entity cart : carts) { + if (!(cart instanceof CommandMinecart cm)) continue; + CommandBlockHolder holder = Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cm); + Color color = holder.isWhitelisted() + ? Color.fromRGB(0x00FF00) + : Color.fromRGB(0xFF0000); + if (holder.isUnknown()) { + color = Color.fromRGB(0); + holder.addToExisting(); + } + currentEntities.add(new EntityHighlight(p, cart, color)); + } + + for (CommandBlockHolder wl : Sentinel.getInstance().getDirector().io.commandBlocks.whitelistedCMDBlocks) { + if (!wl.isPresent() && !wl.isCart()) { + currentBlocks.add(new BlockHighlight(p, wl.loc().translate(), Material.PURPLE_CONCRETE_POWDER)); + } + } + + Set previousBlocks = playerBlockHighlights.getOrDefault(p.getUniqueId(), new HashSet<>()); + Set blocksToAdd = new HashSet<>(currentBlocks); + blocksToAdd.removeAll(previousBlocks); + Set blocksToRemove = new HashSet<>(previousBlocks); + blocksToRemove.removeAll(currentBlocks); + + Set previousEntities = playerEntityHighlights.getOrDefault(p.getUniqueId(), new HashSet<>()); + Set entitiesToAdd = new HashSet<>(currentEntities); + entitiesToAdd.removeAll(previousEntities); + Set entitiesToRemove = new HashSet<>(previousEntities); + entitiesToRemove.removeAll(currentEntities); + + blockHighlights.addAll(blocksToAdd); + blockHighlights.removeAll(blocksToRemove); + playerBlockHighlights.put(p.getUniqueId(), currentBlocks); + + entityHighlights.addAll(entitiesToAdd); + entityHighlights.removeAll(entitiesToRemove); + playerEntityHighlights.put(p.getUniqueId(), currentEntities); + } + + public static void handleDisplay() { + PlayerUtils.forEachTrusted(WandEvents::sortNear); + + Iterator blockIterator = blockHighlights.iterator(); + while (blockIterator.hasNext()) { + BlockHighlight bh = blockIterator.next(); + if (bh.beholder == null || !bh.beholder.isOnline() || bh.loc.distance(bh.beholder.getLocation()) > 10) { + blockIterator.remove(); + playerBlockHighlights.computeIfPresent(bh.beholder.getUniqueId(), (uuid, set) -> { + set.remove(bh); + return set.isEmpty() ? null : set; + }); + } else { + bh.display(); + } + } + + Iterator entityIterator = entityHighlights.iterator(); + while (entityIterator.hasNext()) { + EntityHighlight eh = entityIterator.next(); + if (eh.beholder == null || !eh.beholder.isOnline() || eh.ent.getLocation().distance(eh.beholder.getLocation()) > 10) { + entityIterator.remove(); + playerEntityHighlights.computeIfPresent(eh.beholder.getUniqueId(), (uuid,set) -> { + set.remove(eh); + return set.isEmpty() ? null : set; + }); + } else { + eh.display(); + } + } + + selections.forEach((uuid, selection) -> { + Player p = Bukkit.getPlayer(uuid); + if (p == null || !p.isOnline() || !p.getInventory().getItemInMainHand().isSimilar(SELECTION_WAND)) return; + selection.display(p); + }); + } + + private void setPos2(Player p, Selection selection, Location loc) { + if (selection.getPos2() != null && selection.getPos2().distance(loc) < 0.1) return; + selection.setPos2(loc); + p.sendMessage(Text.prefix("Position 2 set to " + Text.formatLoc(loc))); + } + + private void setPos1(Player p, Selection selection, Location loc) { + if (selection.getPos1() != null && selection.getPos1().distance(loc) < 0.1) return; + selection.setPos1(loc); + p.sendMessage(Text.prefix("Position 1 set to " + Text.formatLoc(loc))); + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/extras/ShadowRealmEvents.java b/src/main/java/me/trouper/sentinel/server/events/extras/ShadowRealmEvents.java new file mode 100644 index 0000000..c2e6a30 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/extras/ShadowRealmEvents.java @@ -0,0 +1,98 @@ +package me.trouper.sentinel.server.events.extras; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag; +import com.github.retrooper.packetevents.protocol.world.Difficulty; +import com.github.retrooper.packetevents.protocol.world.dimension.DimensionTypes; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerCloseWindow; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn; +import io.github.itzispyder.pdk.events.CustomListener; +import io.github.itzispyder.pdk.utils.SchedulerUtils; +import me.trouper.sentinel.Sentinel; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; + +public class ShadowRealmEvents extends PacketListenerAbstract implements CustomListener { + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + Player p = e.getPlayer(); + if (!Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(p.getUniqueId())) return; + SchedulerUtils.later(20,()->{ + enforce(p); + }); + } + + @Override + public void onPacketReceive(PacketReceiveEvent e) { + if (e.getPacketType() == PacketType.Play.Client.KEEP_ALIVE) return; + if (e.getPacketType() == PacketType.Play.Client.TELEPORT_CONFIRM) return; + if (e.getPacketType() == PacketType.Play.Client.CLIENT_SETTINGS) return; + if (e.getPacketType() == PacketType.Play.Client.PLAYER_FLYING) return; + Player player = e.getPlayer(); + if (player == null) return; + if (!Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(player.getUniqueId())) return; + e.setCancelled(true); + } + + @Override + public void onPacketSend(PacketSendEvent e) { + if (e.getPacketType() == PacketType.Play.Server.KEEP_ALIVE) return; + if (e.getPacketType() == PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) return; + if (e.getPacketType() == PacketType.Play.Server.RESPAWN) return; + if (e.getPacketType() == PacketType.Play.Server.DISCONNECT) return; + if (e.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) return; + if (e.getPacketType() == PacketType.Play.Server.CHUNK_DATA) return; + if (e.getPacketType() == PacketType.Play.Server.CHUNK_BATCH_BEGIN) return; + if (e.getPacketType() == PacketType.Play.Server.CHUNK_BATCH_END) return; + if (e.getPacketType() == PacketType.Play.Server.CHUNK_BIOMES) return; + if (e.getPacketType() == PacketType.Play.Server.UNLOAD_CHUNK) return; + if (e.getPacketType() == PacketType.Play.Server.MAP_CHUNK_BULK) return; + + Player player = e.getPlayer(); + if (player == null) return; + if (!Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(player.getUniqueId())) return; + e.setCancelled(true); + } + + public static void enforce(Player p) { + if (p == null || !Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(p.getUniqueId())) return; + sendFakeRespawn(p); + Bukkit.getScheduler().runTaskTimerAsynchronously(Sentinel.getInstance(),(t)->{ + if (p == null || !p.isOnline() || !Sentinel.getInstance().getDirector().io.extraStorage.shadowRealm.containsKey(p.getUniqueId())) t.cancel(); + sendFakePosition(p,0,666,0); + sendCloseScreen(p); + },1,1); + } + + public static void sendFakeRespawn(Player victim) { + if (victim == null || !victim.isOnline()) return; + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + WrapperPlayServerRespawn packet = new WrapperPlayServerRespawn(DimensionTypes.THE_END,"minecraft:the_end", Difficulty.PEACEFUL,1L, GameMode.SPECTATOR,null,false,false,false,null,null,null); + player.sendPacket(packet); + } + + public static void sendCloseScreen(Player victim) { + if (victim == null || !victim.isOnline()) return; + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + if (player == null) return; + WrapperPlayServerCloseWindow packet = new WrapperPlayServerCloseWindow(); + player.sendPacket(packet); + } + + public static void sendFakePosition(Player victim, double x, double y, double z) { + if (victim == null || !victim.isOnline()) return; + var player = PacketEvents.getAPI().getPlayerManager().getUser(victim); + if (player == null) return; + WrapperPlayServerPlayerPositionAndLook packet = new WrapperPlayServerPlayerPositionAndLook(x,y,z,0,90, RelativeFlag.NONE.getMask(),0,false); + player.sendPacket(packet); + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/AbstractViolation.java b/src/main/java/me/trouper/sentinel/server/events/violations/AbstractViolation.java new file mode 100644 index 0000000..bde902e --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/AbstractViolation.java @@ -0,0 +1,169 @@ +package me.trouper.sentinel.server.events.violations; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.events.CustomListener; +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; +import io.papermc.paper.event.player.AsyncChatEvent; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.config.ViolationConfig; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.utils.FileUtils; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import me.trouper.sentinel.utils.trees.ConsoleFormatter; +import me.trouper.sentinel.utils.trees.EmbedFormatter; +import me.trouper.sentinel.utils.trees.HoverFormatter; +import me.trouper.sentinel.utils.trees.Node; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.command.Command; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.function.BiConsumer; + +public abstract class AbstractViolation implements CustomListener { + + public abstract CustomGui getConfigGui(); + public abstract void getMainPage(Inventory inv); + public abstract void onClick(InventoryClickEvent e); + + public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.violationConfig); + + protected void queuePlayer(Player player, BiConsumer action, String currentValue) { + MainGUI.awaitingCallback.add(player.getUniqueId()); + player.closeInventory(); + updater.queuePlayer(player, 20*60, (e)->{ + e.setCancelled(true); + return LegacyComponentSerializer.legacySection().serialize(e.message()); + }, (cfg, newValue) -> { + action.accept(cfg,new Args(newValue.split("\\s+"))); + cfg.save(); + player.sendMessage(Text.prefix("Value updated successfully")); + player.openInventory(getConfigGui().getInventory()); + }); + player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); + } + + public void runActions(String rootName, String rootNamePlayer, Node violationInfo, ActionConfiguration.Builder configuration) { + ActionConfiguration config = configuration.build(); + + Node root = new Node("Sentinel"); + root.addTextLine(rootName); + + if (config.getPlayer() != null) root.addChild(generatePlayerInfo(config.getPlayer())); + + root.addChild(violationInfo); + + root.addChild(configuration.getActionNode()); + + notifyTrusted(root,(rootNamePlayer == null || rootNamePlayer.isBlank()) ? rootName : rootNamePlayer); + if (configuration.isLoggedToDiscord()) EmbedFormatter.sendEmbed(EmbedFormatter.format(root)); + Sentinel.getInstance().getLogger().info(ConsoleFormatter.format(root)); + } + + public void notifyTrusted(Node root, String rootNamePlayer) { + PlayerUtils.forEachTrusted(trusted -> { + trusted.sendMessage(Component.text(Text.prefix(rootNamePlayer)).hoverEvent(Component.text(HoverFormatter.format(root)).asHoverEvent())); + }); + } + + public Node generatePlayerInfo(Player p) { + Node playerInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.playerInfo); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.name, p.getName()); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.uuid, p.getUniqueId().toString()); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.operator, p.isOp() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + playerInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.locationField, Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.locationFormat.formatted(Math.round(p.getX()), Math.round(p.getY()), Math.round(p.getZ()))); + + return playerInfo; + } + + public static Node generateBlockInfo(Block block) { + Node blockInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.blockInfo); + blockInfo.addTextLine(Text.cleanName(block.getType().toString())); + blockInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.worldField,block.getWorld().getName()); + blockInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.blockLocationField,Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.locationFormat.formatted(block.getX(), block.getY(), block.getZ())); + + return blockInfo; + } + + public Node generateCommandBlockInfo(CommandBlock commandBlock) { + Node commandBlockInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.blockInfo); + commandBlockInfo.addTextLine(Text.cleanName(commandBlock.getType().toString())); + commandBlockInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.worldField,commandBlock.getWorld().getName()); + commandBlockInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.blockLocationField,Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.locationFormat.formatted(commandBlock.getX(), commandBlock.getY(), commandBlock.getZ())); + + String command = commandBlock.getCommand(); + if (command == null || command.isBlank()) { + return commandBlockInfo; + } else if (command.length() <= 128) { + commandBlockInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandField, command); + } else { + commandBlockInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandTooLargeField, FileUtils.createCommandLog(command)); + } + + return commandBlockInfo; + } + + public Node generateMinecartInfo(CommandMinecart entity) { + Node minecartInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.minecartInfo); + minecartInfo.addTextLine(Text.cleanName(entity.getType().toString())); + minecartInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.worldField,entity.getWorld().getName()); + minecartInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.cartLocationField,Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.locationFormat.formatted(Math.round(entity.getX()), Math.round(entity.getY()), Math.round(entity.getZ()))); + + String command = entity.getCommand(); + if (command == null || command.isBlank()) { + return minecartInfo; + } else if (command.length() <= 128) { + minecartInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandField, command); + } else { + minecartInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandTooLargeField, FileUtils.createCommandLog(command)); + } + + return minecartInfo; + } + + public Node generateItemInfo(ItemStack item) { + Node itemInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.itemInfo); + itemInfo.addTextLine(Text.cleanName(item.getType().toString())); + itemInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.hasMeta,item.hasItemMeta() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + if (item.hasItemMeta()) { + itemInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.hasName,item.getItemMeta().hasCustomName() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + itemInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.hasLore,item.getItemMeta().hasLore() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + itemInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.hasAttributes,item.getItemMeta().hasAttributeModifiers() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + itemInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.hasEnchants,item.getItemMeta().hasEnchants() ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + itemInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.nbtStored, FileUtils.createNBTLog(item)); + } + + return itemInfo; + } + + public Node generateCommandInfo(String command, Player executor) { + Node commandInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandInfo); + String name = command.split(" ")[0].substring(1); + ServerUtils.verbose("Command Name: " + name); + Command executed = Bukkit.getServer().getCommandMap().getCommand(name); + + commandInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.name,name); + if (command.length() <= 128) { + commandInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandField, command); + } else { + commandInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.commandTooLargeField, FileUtils.createCommandLog(command)); + } + if (executed == null || executed.getPermission() == null) return commandInfo; + commandInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.permissionRequired,executed.getPermission()); + commandInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.permissionSatisfied,executor.hasPermission(executed.getPermission()) ? Sentinel.getInstance().getDirector().io.lang.generic.yes : Sentinel.getInstance().getDirector().io.lang.generic.no); + + return commandInfo; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockBreak.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockBreak.java new file mode 100644 index 0000000..a709f23 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockBreak.java @@ -0,0 +1,146 @@ +package me.trouper.sentinel.server.events.violations.blocks.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.SerialLocation; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandBlockBreak extends AbstractViolation{ + + @EventHandler + public void onBreak(BlockBreakEvent e) { + //ServerUtils.verbose("CommandBlockBreak: Detected the event"); + //ServerUtils.verbose("CommandBlockBreak: Changer is a player"); + Block b = e.getBlock(); + if (!(ServerUtils.isCommandBlock(b))) return; + ServerUtils.verbose("CommandBlockBreak: Block is a command block"); + Player p = e.getPlayer(); + CommandBlock cb = (CommandBlock) b.getState(); + CommandBlockHolder holder = Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cb); + if (PlayerUtils.isTrusted(e.getPlayer())) { + if (!Sentinel.getInstance().getDirector().whitelistManager.autoWhitelist.contains(p.getUniqueId())) { + + return; + } + return; + } + + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled) return; + + ServerUtils.verbose("CommandBlockBreak: is enabled, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.deop) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + generateCommandBlockInfo(cb), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Block Break")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockBreak.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockEdit.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockEdit.java new file mode 100644 index 0000000..1ba0f16 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockEdit.java @@ -0,0 +1,141 @@ +package me.trouper.sentinel.server.events.violations.blocks.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandBlockEdit extends AbstractViolation { + + @EventHandler + private void onCMDBlockChange(EntityChangeBlockEvent e) { + //ServerUtils.verbose("CommandBlockChange: Detected the event"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.enabled) return; + //ServerUtils.verbose("CommandBlockChange: Enabled"); + if (!(e.getEntity() instanceof Player p)) return; + //ServerUtils.verbose("CommandBlockChange: Changer is a player"); + Block b = e.getBlock(); + if (!(ServerUtils.isCommandBlock(b))) + return; + ServerUtils.verbose("CommandBlockChange: Block is a command block"); + CommandBlock cb = (CommandBlock) b.getState(); + if (PlayerUtils.isTrusted(p)) { + if (!Sentinel.getInstance().getDirector().whitelistManager.autoWhitelist.contains(p.getUniqueId())) return; + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cb).addToWhitelist(); + return; + } + ServerUtils.verbose("CommandBlockChange: Not trusted, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.deop) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.edit, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.edit, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + generateCommandBlockInfo(cb), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Block Edit")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockEdit.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockEdit.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockPlace.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockPlace.java new file mode 100644 index 0000000..8df9457 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockPlace.java @@ -0,0 +1,144 @@ +package me.trouper.sentinel.server.events.violations.blocks.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandBlockPlace extends AbstractViolation { + + @EventHandler + public void listen(BlockPlaceEvent e) { + Player p = e.getPlayer(); + Block b = e.getBlockPlaced(); + if (!ServerUtils.isCommandBlock(b)) return; + CommandBlock cb = (CommandBlock) b.getState(); + CommandBlockHolder holder = Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),cb); + if (PlayerUtils.isTrusted(p)) { + holder.addToExisting(); + if (Sentinel.getInstance().getDirector().whitelistManager.autoWhitelist.contains(p.getUniqueId())) holder.addToWhitelist(); + return; + } + + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) { + holder.addToExisting(); + return; + } + + ServerUtils.verbose("CommandBlockPlace: Enabled, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + generateCommandBlockInfo(cb), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Block Place")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockPlace.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockUse.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockUse.java new file mode 100644 index 0000000..8dba11f --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/command/CommandBlockUse.java @@ -0,0 +1,142 @@ +package me.trouper.sentinel.server.events.violations.blocks.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandBlockUse extends AbstractViolation { + + @EventHandler + private void onCMDBlockUse(PlayerInteractEvent e) { + //ServerUtils.verbose("CommandBlockUse: Detected Interaction"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.enabled) return; + //ServerUtils.verbose("CommandBlockUse: Enabled"); + Player p = e.getPlayer(); + if (e.getClickedBlock() == null) return; + //ServerUtils.verbose("CommandBlockUse: Block isn't null"); + Block b = e.getClickedBlock(); + if (!(ServerUtils.isCommandBlock(b))) return; + CommandBlock cb = (CommandBlock) b.getState(); + if (PlayerUtils.isTrusted(p)) { + if (!Sentinel.getInstance().getDirector().whitelistManager.autoWhitelist.contains(p.getUniqueId())) return; + if (Sentinel.getInstance().getDirector().whitelistManager.isWhitelisted(cb)) return; + e.setCancelled(true); + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(), cb).addToWhitelist(); + return; + } + ServerUtils.verbose("CommandBlockUse: Not trusted, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.deop) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlock), + generateCommandBlockInfo(cb), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Block Use")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockUse.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockUse.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockBreak.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockBreak.java new file mode 100644 index 0000000..90f67ed --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockBreak.java @@ -0,0 +1,133 @@ +package me.trouper.sentinel.server.events.violations.blocks.jigsaw; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class JigsawBlockBreak extends AbstractViolation { + + @EventHandler + public void onPlace(BlockBreakEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getBlock(); + if (b == null) return; + if (!Material.JIGSAW.equals(b.getType())) return; + ServerUtils.verbose("StructureBlockBreak: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("StructureBlockBreak: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + generateBlockInfo(b), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Jigsaw Block Break")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.deop = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punish = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.jigsawBlockBreak.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockBreak.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockPlace.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockPlace.java new file mode 100644 index 0000000..8a2db17 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockPlace.java @@ -0,0 +1,134 @@ +package me.trouper.sentinel.server.events.violations.blocks.jigsaw; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class JigsawBlockPlace extends AbstractViolation { + + @EventHandler + public void onPlace(BlockPlaceEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getBlockPlaced(); + if (b == null) return; + if (!b.getType().equals(Material.JIGSAW)) return; + ServerUtils.verbose("StructureBlockPlace: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("StructureBlockPlace: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + generateBlockInfo(b), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Jigsaw Block Place")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.deop = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punish = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.jigsawBlockPlace.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockPlace.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockUse.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockUse.java new file mode 100644 index 0000000..f3318b5 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/jigsaw/JigsawBlockUse.java @@ -0,0 +1,133 @@ +package me.trouper.sentinel.server.events.violations.blocks.jigsaw; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class JigsawBlockUse extends AbstractViolation { + @EventHandler + public void onPlace(PlayerInteractEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getClickedBlock(); + if (b == null) return; + if (!Material.JIGSAW.equals(b.getType())) return; + ServerUtils.verbose("StructureBlockUse: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("StructureBlockUse: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.jigsawBlock), + generateBlockInfo(b), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Jigsaw Block Use")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.deop = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punish = !Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.jigsawBlockUse.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.jigsawBlockUse.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockBreak.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockBreak.java new file mode 100644 index 0000000..8dd9aef --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockBreak.java @@ -0,0 +1,134 @@ +package me.trouper.sentinel.server.events.violations.blocks.structure; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class StructureBlockBreak extends AbstractViolation { + + @EventHandler + public void onPlace(BlockBreakEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getBlock(); + if (b == null) return; + if (!Material.STRUCTURE_BLOCK.equals(b.getType())) return; + ServerUtils.verbose("StructureBlockBreak: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("StructureBlockBreak: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + generateBlockInfo(b), + config + ); + } + + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Structure Block Break")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.deop = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punish = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.structureBlockBreak.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockBreak.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockPlace.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockPlace.java new file mode 100644 index 0000000..9b90594 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockPlace.java @@ -0,0 +1,132 @@ +package me.trouper.sentinel.server.events.violations.blocks.structure; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class StructureBlockPlace extends AbstractViolation { + @EventHandler + public void onPlace(BlockPlaceEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getBlockPlaced(); + if (b == null) return; + if (!b.getType().equals(Material.STRUCTURE_BLOCK)) return; + ServerUtils.verbose("StructureBlockPlace: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("StructureBlockPlace: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + generateBlockInfo(b), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Structure Block Place")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.deop = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punish = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.structureBlockPlace.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockPlace.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockUse.java b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockUse.java new file mode 100644 index 0000000..876f4fe --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/blocks/structure/StructureBlockUse.java @@ -0,0 +1,133 @@ +package me.trouper.sentinel.server.events.violations.blocks.structure; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class StructureBlockUse extends AbstractViolation { + @EventHandler + public void onPlace(PlayerInteractEvent e) { + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockPlace.enabled) return; + Player p = e.getPlayer(); + Block b = e.getClickedBlock(); + if (b == null) return; + if (!Material.STRUCTURE_BLOCK.equals(b.getType())) return; + ServerUtils.verbose("StructureBlockUse: Block is a Structure block"); + if (PlayerUtils.isTrusted(p)) return; + + ServerUtils.verbose("StructureBlockUse: Not trusted, performing action"); + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.deop) + .cancel(true) + .setEvent(e) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.structureBlock), + generateBlockInfo(b), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Structure Block Use")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.deop = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punish = !Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.structureBlockUse.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.structureBlockUse.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/command/DangerousCommand.java b/src/main/java/me/trouper/sentinel/server/events/violations/command/DangerousCommand.java new file mode 100644 index 0000000..48f15da --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/command/DangerousCommand.java @@ -0,0 +1,140 @@ +package me.trouper.sentinel.server.events.violations.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class DangerousCommand extends AbstractViolation { + @EventHandler + private void onCommand(PlayerCommandPreprocessEvent e) { + Player p = e.getPlayer(); + if (PlayerUtils.isTrusted(p)) return; + String label = e.getMessage().substring(1).split(" ")[0]; + String args = e.getMessage(); + + if (Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.commands.contains(label) && Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.enabled) { + e.setCancelled(true); + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.deop) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.dangerousCommand), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.dangerousCommand), + generateCommandInfo(args, p), + config + ); + } + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Dangerous Command Check")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i, Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + inv.setItem(22,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.commands,Material.CRIMSON_HANGING_SIGN,"Commands","Commands that will flag this check.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { + cfg.commandExecute.dangerous.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 22 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { + cfg.commandExecute.dangerous.commands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.commands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.dangerous.commands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/command/LoggedCommand.java b/src/main/java/me/trouper/sentinel/server/events/violations/command/LoggedCommand.java new file mode 100644 index 0000000..e6b839e --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/command/LoggedCommand.java @@ -0,0 +1,110 @@ +package me.trouper.sentinel.server.events.violations.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class LoggedCommand extends AbstractViolation { + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent e) { + Player p = e.getPlayer(); + if (PlayerUtils.isTrusted(p)) return; + String label = e.getMessage().substring(1).split(" ")[0]; + String args = e.getMessage(); + + if (Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.commands.contains(label) && Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.enabled) { + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setPlayer(p) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.loggedCommand), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.loggedCommand), + generateCommandInfo(args, p), + config + ); + } + } + + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Logged Command Check")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(11,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.logToDiscord,Items.configItem("Log to Discord",Material.OAK_LOG,"If this check will log to discord"))); + inv.setItem(15,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.commands,Material.CRIMSON_HANGING_SIGN,"Commands","Commands that will flag this check")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 11 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 15 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { + cfg.commandExecute.logged.commands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.commands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.logged.commands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/command/SpecificCommand.java b/src/main/java/me/trouper/sentinel/server/events/violations/command/SpecificCommand.java new file mode 100644 index 0000000..3adc88a --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/command/SpecificCommand.java @@ -0,0 +1,117 @@ +package me.trouper.sentinel.server.events.violations.command; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class SpecificCommand extends AbstractViolation { + + @EventHandler + private void onCommand(PlayerCommandPreprocessEvent e) { + Player p = e.getPlayer(); + if (PlayerUtils.isTrusted(p)) return; + String label = e.getMessage().substring(1).split(" ")[0]; + String args = e.getMessage(); + + if (label.contains(":") && Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.enabled) { + e.setCancelled(true); + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.specificCommand), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.run, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.specificCommand), + generateCommandInfo(args, p), + config + ); + } + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Specific Command Check")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack top = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.enabled) { + top = Items.GREEN; + } + + for (int i = 0; i < 9; i++) { + inv.setItem(i,top); + } + + inv.setItem(26,Items.BACK); + inv.setItem(4,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(11,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"If this check will run the punishment commands"))); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(15,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punishmentCommands,Material.DIAMOND_AXE,"Commands","Commands that will flag this check")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 4 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 11 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 15 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandExecute.specific.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandExecute.specific.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartBreak.java b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartBreak.java new file mode 100644 index 0000000..2cfe79d --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartBreak.java @@ -0,0 +1,145 @@ +package me.trouper.sentinel.server.events.violations.entities; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandMinecartBreak extends AbstractViolation { + @EventHandler + public void onBreak(EntityDamageEvent e) { + //ServerUtils.verbose("CommandBlockBreak: Detected the event"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled) return; + //ServerUtils.verbose("CommandBlockBreak: Changer is a player"); + if (!(e.getEntity() instanceof CommandMinecart s)) return; + if (e.getDamageSource() == null) { + e.setCancelled(true); + return; + } + if (e.getDamageSource().getCausingEntity() == null) { + e.setCancelled(true); + return; + } + if (!(e.getDamageSource().getCausingEntity() instanceof Player p)) { + e.setCancelled(true); + return; + } + if (PlayerUtils.isTrusted(p)) { + if (Sentinel.getInstance().getDirector().whitelistManager.getFromExisting(s.getLocation()).isWhitelisted()) return; + Sentinel.getInstance().getDirector().whitelistManager.getFromExisting(s.getLocation()).removeFromExisting(); + return; + } + ServerUtils.verbose("Not trusted, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setEntity(s) + .setPlayer(p) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.deop) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punish) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.brake, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + generateMinecartInfo(s), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Cart Break")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockMinecartBreak.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartPlace.java b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartPlace.java new file mode 100644 index 0000000..6fea190 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartPlace.java @@ -0,0 +1,196 @@ +package me.trouper.sentinel.server.events.violations.entities; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.vehicle.VehicleCreateEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + +public class CommandMinecartPlace extends AbstractViolation { + + private final ConcurrentHashMap queuedInteractions = new ConcurrentHashMap<>(); + + private UUID getPlayer(Location loc) { + ServerUtils.verbose("Getting responsible player for a location"); + AtomicReference player = new AtomicReference<>(); + + queuedInteractions.forEach((location,uuid)->{ + if (player.get() == null) { + ServerUtils.verbose("Loop is running"); + if (loc.distance(location) < 1) { + ServerUtils.verbose("Found a matching minecart"); + player.set(uuid); + queuedInteractions.remove(location); + } + } + }); + return player.get(); + } + + @EventHandler + private void onVehicleCreate(VehicleCreateEvent e) { + //ServerUtils.verbose("Vehicle Creation Event"); + if (!(e.getVehicle() instanceof CommandMinecart commandMinecart)) return; + if (queuedInteractions.isEmpty()) { + ServerUtils.verbose("Queue is empty, preventing"); + e.setCancelled(true); + return; + } + UUID uuid = getPlayer(e.getVehicle().getLocation()); + if (uuid == null) { + ServerUtils.verbose("UUID is null, preventing"); + e.setCancelled(true); + return; + } + Player p = Bukkit.getPlayer(uuid); + if (p == null) { + ServerUtils.verbose("Player is null, preventing"); + e.setCancelled(true); + return; + } + + if (PlayerUtils.isTrusted(p)) { + ServerUtils.verbose("Player is trusted, allowing."); + Sentinel.getInstance().getDirector().whitelistManager.generateHolder(p.getUniqueId(),commandMinecart) + .addToExisting(); + return; + } + + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punish) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.deop) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.logToDiscord); + + // Remove the command block minecart from the player's inventory + p.getInventory().remove(Material.COMMAND_BLOCK_MINECART); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.place, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + generateMinecartInfo(commandMinecart), + config + ); + } + + @EventHandler + private void onIneteract(PlayerInteractEvent e) { + //ServerUtils.verbose("Player Interaction Event"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.enabled) return; + //ServerUtils.verbose("MinecartCommandPlace: Check is enabled"); + Player p = e.getPlayer(); + if (e.getItem() == null) return; + //ServerUtils.verbose("MinecartCommandPlace: Item isn't null"); + if (e.getClickedBlock() == null) return; + //ServerUtils.verbose("MinecartCommandPlace: Clicked block isn't null"); + if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return; + ServerUtils.verbose("Item is a minecart command"); + if (!(e.getClickedBlock().getType() == Material.RAIL || e.getClickedBlock().getType() == Material.POWERED_RAIL || e.getClickedBlock().getType() == Material.ACTIVATOR_RAIL || e.getClickedBlock().getType() == Material.DETECTOR_RAIL)) return; + ServerUtils.verbose("Clicked block is a rail, adding to list"); + + queuedInteractions.put(e.getClickedBlock().getLocation(),p.getUniqueId()); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Cart Place")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockMinecartPlace.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartPlace.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartUse.java b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartUse.java new file mode 100644 index 0000000..9264f9c --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/entities/CommandMinecartUse.java @@ -0,0 +1,132 @@ +package me.trouper.sentinel.server.events.violations.entities; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CommandMinecartUse extends AbstractViolation { + + @EventHandler + private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) { + //ServerUtils.verbose("MinecartCommandUse: Detected Interaction with entity"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.enabled) return; + //ServerUtils.verbose("MinecartCommandUse: Enabled"); + Player p = e.getPlayer(); + if (!(e.getRightClicked() instanceof CommandMinecart s)) return; + ServerUtils.verbose("MinecartCommandUse: Entity is minecart command"); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("MinecartCommandUse: Not trusted, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .setEntity(s) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punish) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.deop) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.use, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandMinecart), + generateMinecartInfo(s), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Cart Use")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.deop = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punish = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.commandBlockMinecartUse.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartUse.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/ChatEvent.java b/src/main/java/me/trouper/sentinel/server/events/violations/players/ChatEvent.java similarity index 54% rename from src/main/java/me/trouper/sentinel/server/events/ChatEvent.java rename to src/main/java/me/trouper/sentinel/server/events/violations/players/ChatEvent.java index 9cb6b7a..a007717 100644 --- a/src/main/java/me/trouper/sentinel/server/events/ChatEvent.java +++ b/src/main/java/me/trouper/sentinel/server/events/violations/players/ChatEvent.java @@ -1,9 +1,27 @@ -package me.trouper.sentinel.server.events; +package me.trouper.sentinel.server.events.violations.players; import io.github.itzispyder.pdk.events.CustomListener; import io.github.itzispyder.pdk.utils.SchedulerUtils; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockEdit; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockUse; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockUse; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockUse; +import me.trouper.sentinel.server.events.violations.command.DangerousCommand; +import me.trouper.sentinel.server.events.violations.command.LoggedCommand; +import me.trouper.sentinel.server.events.violations.command.SpecificCommand; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartBreak; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartPlace; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartUse; +import me.trouper.sentinel.server.events.violations.whitelist.CommandBlockExecute; +import me.trouper.sentinel.server.events.violations.whitelist.CommandMinecartExecute; import me.trouper.sentinel.server.functions.chatfilter.profanity.ProfanityFilter; import me.trouper.sentinel.server.functions.chatfilter.spam.SpamFilter; import me.trouper.sentinel.server.functions.chatfilter.unicode.UnicodeFilter; @@ -13,10 +31,6 @@ import me.trouper.sentinel.server.gui.config.chat.ProfanityFilterGUI; import me.trouper.sentinel.server.gui.config.chat.SpamFilterGUI; import me.trouper.sentinel.server.gui.config.chat.UnicodeFilterGUI; import me.trouper.sentinel.server.gui.config.chat.UrlFilterGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.*; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.DangerousCMDGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.LoggedCMDGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.SpecificCMDGUI; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import org.bukkit.entity.Player; @@ -45,15 +59,25 @@ public class ChatEvent implements CustomListener { UrlFilterGUI.updater.invokeCallbacks(e); ProfanityFilterGUI.updater.invokeCallbacks(e); SpamFilterGUI.updater.invokeCallbacks(e); - DangerousCMDGUI.updater.invokeCallbacks(e); - LoggedCMDGUI.updater.invokeCallbacks(e); - SpecificCMDGUI.updater.invokeCallbacks(e); - CBEditGUI.updater.invokeCallbacks(e); - CBMCPlaceGUI.updater.invokeCallbacks(e); - CBMCUseGUI.updater.invokeCallbacks(e); - CBPlaceGUI.updater.invokeCallbacks(e); - CBUseGUI.updater.invokeCallbacks(e); - HotbarActionGUI.updater.invokeCallbacks(e); + DangerousCommand.updater.invokeCallbacks(e); + LoggedCommand.updater.invokeCallbacks(e); + SpecificCommand.updater.invokeCallbacks(e); + CommandBlockBreak.updater.invokeCallbacks(e); + CommandBlockEdit.updater.invokeCallbacks(e); + CommandBlockPlace.updater.invokeCallbacks(e); + CommandBlockUse.updater.invokeCallbacks(e); + JigsawBlockBreak.updater.invokeCallbacks(e); + JigsawBlockPlace.updater.invokeCallbacks(e); + JigsawBlockUse.updater.invokeCallbacks(e); + StructureBlockBreak.updater.invokeCallbacks(e); + StructureBlockPlace.updater.invokeCallbacks(e); + StructureBlockUse.updater.invokeCallbacks(e); + CommandMinecartBreak.updater.invokeCallbacks(e); + CommandMinecartPlace.updater.invokeCallbacks(e); + CommandMinecartUse.updater.invokeCallbacks(e); + CommandBlockExecute.updater.invokeCallbacks(e); + CommandMinecartExecute.updater.invokeCallbacks(e); + CreativeHotbar.updater.invokeCallbacks(e); }); } return; @@ -65,7 +89,7 @@ public class ChatEvent implements CustomListener { handle(p, "sentinel.chatfilter.unicode.bypass", - Sentinel.mainConfig.chat.unicodeFilter.enabled, "unicode", + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.enabled, "unicode", e, UnicodeFilter::handleUnicodeFilter); @@ -73,7 +97,7 @@ public class ChatEvent implements CustomListener { handle(p, "sentinel.chatfilter.url.bypass", - Sentinel.mainConfig.chat.urlFilter.enabled, "url", + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.enabled, "url", e, UrlFilter::handleUrlFilter); @@ -81,7 +105,7 @@ public class ChatEvent implements CustomListener { handle(p, "sentinel.chatfilter.spam.bypass", - Sentinel.mainConfig.chat.spamFilter.enabled, + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.enabled, "spam", e, SpamFilter::handleSpamFilter); @@ -90,7 +114,7 @@ public class ChatEvent implements CustomListener { handle(p, "sentinel.chatfilter.swear.bypass", - Sentinel.mainConfig.chat.profanityFilter.enabled, + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.enabled, "swear", e, ProfanityFilter::handleProfanityFilter); diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/players/CreativeHotbar.java b/src/main/java/me/trouper/sentinel/server/events/violations/players/CreativeHotbar.java new file mode 100644 index 0000000..cd7bcb7 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/players/CreativeHotbar.java @@ -0,0 +1,141 @@ +package me.trouper.sentinel.server.events.violations.players; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.functions.itemchecks.ItemCheck; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.PlayerUtils; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCreativeEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class CreativeHotbar extends AbstractViolation { + + @EventHandler + private void onNBTPull(InventoryCreativeEvent e) { + //ServerUtils.verbose("NBT: Detected creative mode action"); + if (!Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.enabled) return; + ServerUtils.verbose("NBT: Enabled"); + if (!(e.getWhoClicked() instanceof Player p)) return; + ServerUtils.verbose("NBT: Clicker is a player"); + if (e.getCursor() == null) return; // Well it threw an exception during testing, so it isn't always false! + ServerUtils.verbose("NBT: Cursor isn't null"); + ItemStack i = e.getCursor(); + if (PlayerUtils.isTrusted(p)) return; + ServerUtils.verbose("NBT: Not trusted"); + if (e.getCursor().getItemMeta() == null) return; + ServerUtils.verbose("NBT: Cursor has meta"); + if (!(i.hasItemMeta() && i.getItemMeta() != null)) return; + ServerUtils.verbose("NBT: Item has meta"); + if (new ItemCheck().passes(i)) return; + ServerUtils.verbose("NBT: Item doesn't pass, performing action"); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setPlayer(p) + .cancel(true) + .punish(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punish) + .deop(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.deop) + .setPunishmentCommands(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punishmentCommands) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.logToDiscord); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.grab, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.nbtItem), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormatPlayer.formatted(p.getName(), Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.grab, Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.nbtItem), + generateItemInfo(i), + config + ); + } + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Creative Hotbar Check")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i, Items.BLANK); + } + + ItemStack ring = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.enabled) { + ring = Items.GREEN; + } + + List ringList = List.of(3,4,5,12,14,21,22,23); + + for (Integer i : ringList) { + inv.setItem(i,ring); + } + + inv.setItem(26,Items.BACK); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(2,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(6,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + + switch (e.getSlot()) { + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 2 -> { + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.deop = !Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.deop; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 20 -> { + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 6 -> { + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punish = !Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punish; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + case 24 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { + cfg.creativeHotbarAction.punishmentCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punishmentCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.creativeHotbarAction.punishmentCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/PluginCloakingEvent.java b/src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingEvents.java similarity index 59% rename from src/main/java/me/trouper/sentinel/server/events/PluginCloakingEvent.java rename to src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingEvents.java index 549ed74..e29d763 100644 --- a/src/main/java/me/trouper/sentinel/server/events/PluginCloakingEvent.java +++ b/src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingEvents.java @@ -1,9 +1,8 @@ -package me.trouper.sentinel.server.events; +package me.trouper.sentinel.server.events.violations.players; import io.github.itzispyder.pdk.events.CustomListener; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -13,7 +12,7 @@ import org.bukkit.event.player.PlayerQuitEvent; import java.util.List; -public class PluginCloakingEvent implements CustomListener { +public class PluginCloakingEvents implements CustomListener { @EventHandler public void onQuit(PlayerQuitEvent e) { @@ -23,7 +22,7 @@ public class PluginCloakingEvent implements CustomListener { @EventHandler public void onCommand(PlayerCommandPreprocessEvent e) { - if (!Sentinel.mainConfig.plugin.pluginHider) return; + if (!Sentinel.getInstance().getDirector().io.mainConfig.plugin.pluginHider) return; Player p = e.getPlayer(); if (PlayerUtils.isTrusted(p)) return; @@ -33,16 +32,16 @@ public class PluginCloakingEvent implements CustomListener { message = message.substring(1); } - for (String alias : Sentinel.advConfig.commandsWithPluginAccess) { + for (String alias : Sentinel.getInstance().getDirector().io.advConfig.commandsWithPluginAccess) { if (!message.startsWith(alias)) continue; e.setCancelled(true); - p.sendMessage(Text.color(Sentinel.lang.permissions.noPlugins)); + p.sendMessage(Text.color(Sentinel.getInstance().getDirector().io.lang.permissions.noPlugins)); } } @EventHandler public void onTabComplete(PlayerCommandSendEvent e) { - if (!Sentinel.mainConfig.plugin.pluginHider) return; + if (!Sentinel.getInstance().getDirector().io.mainConfig.plugin.pluginHider) return; Player p = e.getPlayer(); if (PlayerUtils.isTrusted(p)) return; @@ -52,15 +51,15 @@ public class PluginCloakingEvent implements CustomListener { e.getCommands().remove(command); continue; } - if (Sentinel.advConfig.commandsWithPluginAccess.contains(command)) { + if (Sentinel.getInstance().getDirector().io.advConfig.commandsWithPluginAccess.contains(command)) { e.getCommands().remove(command); continue; } } - ServerUtils.verbose("Removed all the plugin specific commands form the listing. It now contains %s".formatted(e.getCommands().stream().toList().toString())); - for (String fakePlugin : Sentinel.advConfig.fakePlugins) { + //ServerUtils.verbose("Removed all the plugin specific commands form the listing. It now contains %s".formatted(e.getCommands().stream().toList().toString())); + for (String fakePlugin : Sentinel.getInstance().getDirector().io.advConfig.fakePlugins) { e.getCommands().add(fakePlugin + ":" + fakePlugin); } - ServerUtils.verbose("Added the fake plugins, now it contains this: %s".formatted(e.getCommands().stream().toList().toString())); + //ServerUtils.verbose("Added the fake plugins, now it contains this: %s".formatted(e.getCommands().stream().toList().toString())); } } diff --git a/src/main/java/me/trouper/sentinel/server/events/PluginCloakingPacket.java b/src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingPacket.java similarity index 87% rename from src/main/java/me/trouper/sentinel/server/events/PluginCloakingPacket.java rename to src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingPacket.java index 3b6a440..d791205 100644 --- a/src/main/java/me/trouper/sentinel/server/events/PluginCloakingPacket.java +++ b/src/main/java/me/trouper/sentinel/server/events/violations/players/PluginCloakingPacket.java @@ -1,4 +1,4 @@ -package me.trouper.sentinel.server.events; +package me.trouper.sentinel.server.events.violations.players; import com.github.retrooper.packetevents.event.PacketListenerAbstract; import com.github.retrooper.packetevents.event.PacketListenerPriority; @@ -29,7 +29,7 @@ public class PluginCloakingPacket extends PacketListenerAbstract { @Override public void onPacketReceive(PacketReceiveEvent event) { - if (!Sentinel.mainConfig.plugin.pluginHider) return; + if (!Sentinel.getInstance().getDirector().io.mainConfig.plugin.pluginHider) return; if (event.getPacketType() != PacketType.Play.Client.TAB_COMPLETE) return; WrapperPlayClientTabComplete wrapper = new WrapperPlayClientTabComplete(event); @@ -38,7 +38,7 @@ public class PluginCloakingPacket extends PacketListenerAbstract { if (PlayerUtils.isTrusted(player)) return; String text = wrapper.getText(); - for (String versionAlias : Sentinel.advConfig.pluginTabCompletions) { + for (String versionAlias : Sentinel.getInstance().getDirector().io.advConfig.pluginTabCompletions) { if (!text.contains(versionAlias)) continue; ServerUtils.verbose("Caught a version command tab completion. (%s -> %s)".formatted(text,versionAlias)); tabReplaceQueue.add(player.getUniqueId()); @@ -50,7 +50,7 @@ public class PluginCloakingPacket extends PacketListenerAbstract { @Override public void onPacketSend(PacketSendEvent event) { - if (!Sentinel.mainConfig.plugin.pluginHider) return; + if (!Sentinel.getInstance().getDirector().io.mainConfig.plugin.pluginHider) return; Player player = (Player) event.getPlayer(); if (player == null) return; @@ -63,7 +63,7 @@ public class PluginCloakingPacket extends PacketListenerAbstract { ServerUtils.verbose("Player was queued for replacement, setting tab completions."); WrapperPlayServerTabComplete wrapper = new WrapperPlayServerTabComplete(event); List matches = new ArrayList<>(); - for (String fakePlugin : Sentinel.advConfig.fakePlugins) { + for (String fakePlugin : Sentinel.getInstance().getDirector().io.advConfig.fakePlugins) { matches.add(new WrapperPlayServerTabComplete.CommandMatch(fakePlugin)); } wrapper.setCommandMatches(matches); diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandBlockExecute.java b/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandBlockExecute.java new file mode 100644 index 0000000..f4acc19 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandBlockExecute.java @@ -0,0 +1,155 @@ +package me.trouper.sentinel.server.events.violations.whitelist; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.AntiNukeGUI; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class CommandBlockExecute extends AbstractViolation { + + @EventHandler + private void commandBlockExecute(ServerCommandEvent e) { + //ServerUtils.verbose("Handling command block event: " + e.getCommand()); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled) return; + //ServerUtils.verbose("Whitelist not disabled"); + if (!(e.getSender() instanceof BlockCommandSender s)) return; + //ServerUtils.verbose("Sender is command block"); + + Block block = s.getBlock(); + CommandBlock cb = (CommandBlock) block.getState(); + + String label = cb.getCommand(); + ServerUtils.verbose("Command block is set to %s.".formatted(label)); + label = label.split(" ")[0]; + if (label.startsWith("/")) label = label.substring(1); + ServerUtils.verbose("It's label is %s.".formatted(label)); + + boolean isRestricted = Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.disabledCommands.contains(label); + boolean canRun = Sentinel.getInstance().getDirector().whitelistManager.isWhitelisted(cb); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setBlock(block) + .cancel(true) + .destroyBlock(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyBlock) + .restoreBlock(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.attemptRestore) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.logToDiscord); + + if (isRestricted) { + ServerUtils.verbose("Command block is using a restricted command."); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockRestriction), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted( Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockRestriction), + generateCommandBlockInfo(cb), + config + ); + } else if (!canRun) { + ServerUtils.verbose("Command block can't run."); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockWhitelist), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockWhitelist), + generateCommandBlockInfo(cb), + config + ); + } + } + + + @Override + public CustomGui getConfigGui() { + return CustomGui.create() + .title(Text.color("&6&lSentinel &8»&0 Command Block Whitelist")) + .size(27) + .onDefine(this::getMainPage) + .defineMain(this::onClick) + .define(26, Items.BACK, e->{ + e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); + }) + .build(); + } + + @Override + public void getMainPage(Inventory inv) { + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i,Items.BLANK); + } + + ItemStack top = Items.RED; + if (Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled) { + top = Items.GREEN; + } + + for (int i = 0; i < 9; i++) { + inv.setItem(i,top); + } + + inv.setItem(26,Items.BACK); + inv.setItem(4,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); + inv.setItem(11,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyBlock,Items.configItem("Destroy",Material.NETHERITE_PICKAXE,"Destroy the offending command-block"))); + inv.setItem(12,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyCart,Items.configItem("Destroy",Material.TNT_MINECART,"Destroy the offending command-cart"))); + inv.setItem(13,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.attemptRestore,Items.configItem("Restore",Material.COMMAND_BLOCK,"Attempt to restore the block if a \nwhitelisted one exists at the location"))); + inv.setItem(14,Items.booleanItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); + inv.setItem(15,Items.stringListItem(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.disabledCommands,Material.CRIMSON_HANGING_SIGN,"Commands","Commands no command blocks can run. \nWorks even if whitelist is disabled. \nYou must add plugin specific versions yourself.")); + } + + @Override + public void onClick(InventoryClickEvent e) { + e.setCancelled(true); + if (!MainGUI.verify((Player) e.getWhoClicked())) return; + switch (e.getSlot()) { + case 4 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 11 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyBlock = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyBlock; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 12 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyCart = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyCart; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 13 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.attemptRestore = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.attemptRestore; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 14 -> { + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.logToDiscord = !Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.logToDiscord; + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + case 15 -> { + if (e.isLeftClick()) { + queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { + cfg.commandBlockWhitelist.disabledCommands.add(args.getAll().toString()); + },"" + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.disabledCommands); + return; + } + Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.disabledCommands.clear(); + getMainPage(e.getInventory()); + Sentinel.getInstance().getDirector().io.violationConfig.save(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandMinecartExecute.java b/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandMinecartExecute.java new file mode 100644 index 0000000..fdb3b77 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/events/violations/whitelist/CommandMinecartExecute.java @@ -0,0 +1,79 @@ +package me.trouper.sentinel.server.events.violations.whitelist; + +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.events.violations.AbstractViolation; +import me.trouper.sentinel.server.functions.helpers.ActionConfiguration; +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.entity.minecart.CommandMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.inventory.Inventory; + +public class CommandMinecartExecute extends AbstractViolation { + + @EventHandler + public void onExecute(ServerCommandEvent e) { + //ServerUtils.verbose("Handling command block event: " + e.getCommand()); + if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.enabled) return; + //ServerUtils.verbose("Whitelist not disabled"); + if (!(e.getSender() instanceof CommandMinecart s)) return; + //ServerUtils.verbose("Sender is command block"); + + + String label = s.getCommand(); + ServerUtils.verbose("Command block is set to %s.".formatted(label)); + label = label.split(" ")[0]; + if (label.startsWith("/")) label = label.substring(1); + ServerUtils.verbose("It's label is %s.".formatted(label)); + + boolean isRestricted = Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.disabledCommands.contains(label); + boolean canRun = Sentinel.getInstance().getDirector().whitelistManager.isWhitelisted(s); + + ActionConfiguration.Builder config = new ActionConfiguration.Builder() + .setEvent(e) + .setEntity(s) + .cancel(true) + .removeEntity(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.destroyCart) + .logToDiscord(Sentinel.getInstance().getDirector().io.violationConfig.commandBlockWhitelist.logToDiscord); + + if (isRestricted) { + ServerUtils.verbose("Command cart is using a restricted command."); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockRestriction), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted( Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockRestriction), + generateMinecartInfo(s), + config + ); + return; + } + + if (!canRun) { + ServerUtils.verbose("Command cart can't run."); + + runActions( + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockWhitelist), + Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.rootNameFormat.formatted(Sentinel.getInstance().getDirector().io.lang.violations.protections.rootName.commandBlockWhitelist), + generateMinecartInfo(s), + config + ); + } + } + + @Override + public CustomGui getConfigGui() { + return new CommandBlockExecute().getConfigGui(); + } + + @Override + public void getMainPage(Inventory inv) { + new CommandBlockExecute().getMainPage(inv); + } + + @Override + public void onClick(InventoryClickEvent e) { + new CommandBlockExecute().onClick(e); + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/AbstractActionHandler.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/AbstractActionHandler.java index 8c70761..1e9ff7f 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/AbstractActionHandler.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/AbstractActionHandler.java @@ -1,9 +1,8 @@ package me.trouper.sentinel.server.functions.chatfilter; import io.github.itzispyder.pdk.utils.discord.DiscordEmbed; +import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; -import me.trouper.sentinel.server.functions.helpers.FilterHelpers; import me.trouper.sentinel.utils.trees.ConsoleFormatter; import me.trouper.sentinel.utils.trees.EmbedFormatter; import me.trouper.sentinel.utils.trees.Node; @@ -11,11 +10,11 @@ import me.trouper.sentinel.utils.trees.Node; public abstract class AbstractActionHandler { public void run(T response) { - FalsePositiveReporting.reports.put(response.getReport().getId(), response.getReport()); + Sentinel.getInstance().getDirector().reportHandler.reports.put(response.getReport().getId(), response.getReport()); Node tree = buildTree(response); if (response.isBlocked()) { - FilterHelpers.restrictMessage(response.getEvent(),!shouldWarnPlayer(response)); + restrictMessage(response.getEvent(),!shouldWarnPlayer(response)); } if (response.isPunished()) { punish(response); @@ -36,11 +35,20 @@ public abstract class AbstractActionHandler { protected abstract boolean shouldWarnPlayer(T response); protected void consoleLog(Node tree) { - Sentinel.log.info(ConsoleFormatter.format(tree)); + Sentinel.getInstance().getLogger().info(ConsoleFormatter.format(tree)); } protected void discordNotification(Node tree) { DiscordEmbed embed = EmbedFormatter.format(tree); EmbedFormatter.sendEmbed(embed); } + + protected void restrictMessage(AsyncChatEvent event, boolean silent) { + if (silent) { + event.viewers().clear(); + event.viewers().add(event.getPlayer()); + } else { + event.setCancelled(true); + } + } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.java index 1c803de..7b74979 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityAction.java @@ -2,6 +2,7 @@ package me.trouper.sentinel.server.functions.chatfilter.profanity; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.server.functions.chatfilter.AbstractActionHandler; +import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import me.trouper.sentinel.utils.trees.HoverFormatter; @@ -14,11 +15,11 @@ public class ProfanityAction extends AbstractActionHandler { @Override public void punish(ProfanityResponse response) { if (response.getSeverity().equals(Severity.SLUR)) { - for (String slurCommand : Sentinel.mainConfig.chat.profanityFilter.strictPunishCommands) { + for (String slurCommand : Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.strictPunishCommands) { ServerUtils.sendCommand(slurCommand.replaceAll("%player%", response.getPlayer().getName())); } } - for (String swearCommand : Sentinel.mainConfig.chat.profanityFilter.profanityPunishCommands) { + for (String swearCommand : Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.profanityPunishCommands) { ServerUtils.sendCommand(swearCommand.replaceAll("%player%", response.getPlayer().getName())); } } @@ -27,21 +28,21 @@ public class ProfanityAction extends AbstractActionHandler { public void staffWarning(ProfanityResponse response, Node tree) { String messageText = Text.prefix("&b&n%s&r &7%s &8(&4%s&7/&c%s&8)".formatted( response.getPlayer().getName(), - response.isPunished() ? Sentinel.lang.violations.chat.profanity.autoPunishNotification : Sentinel.lang.violations.chat.profanity.preventNotification, + response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.autoPunishNotification : Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.preventNotification, ProfanityFilter.scoreMap.getOrDefault(response.getPlayer().getUniqueId(), 0), - Sentinel.mainConfig.chat.profanityFilter.punishScore + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.punishScore )); String hoverText = HoverFormatter.format(tree); - ServerUtils.forEachPlayer(player -> { + PlayerUtils.forEachPlayer(player -> { if (player.hasPermission("sentinel.chatfilter.profanity.view")) player.sendMessage(Component.text(messageText).hoverEvent(Component.text(hoverText).asHoverEvent())); }); } @Override public void playerWarning(ProfanityResponse response) { - String message = Text.prefix(response.isPunished() ? Sentinel.lang.violations.chat.profanity.autoPunishWarning : Sentinel.lang.violations.chat.profanity.preventWarning); - String hoverText = Sentinel.lang.automatedActions.reportable; + String message = Text.prefix(response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.autoPunishWarning : Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.preventWarning); + String hoverText = Sentinel.getInstance().getDirector().io.lang.automatedActions.reportable; String command = "/sentinelcallback fpreport %s".formatted(response.getReport().getId()); response.getPlayer().sendMessage(Component.text(message) .hoverEvent(Component.text(hoverText).asHoverEvent()) @@ -51,22 +52,22 @@ public class ProfanityAction extends AbstractActionHandler { @Override public Node buildTree(ProfanityResponse response) { Node root = new Node("Sentinel"); - root.addTextLine(Sentinel.lang.violations.chat.profanity.treeTitle); + root.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.treeTitle); - Node playerInfo = new Node(Sentinel.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); - playerInfo.addKeyValue(Sentinel.lang.violations.chat.profanity.score, "%s/%s".formatted(ProfanityFilter.scoreMap.getOrDefault(response.getPlayer().getUniqueId(),0),Sentinel.mainConfig.chat.profanityFilter.punishScore)); + Node playerInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.score, "%s/%s".formatted(ProfanityFilter.scoreMap.getOrDefault(response.getPlayer().getUniqueId(),0),Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.punishScore)); root.addChild(playerInfo); - Node reportInfo = new Node(Sentinel.lang.violations.chat.profanity.reportInfoTitle); - reportInfo.addField(Sentinel.lang.violations.chat.originalMessage, response.getOriginalMessage()); - reportInfo.addField(Sentinel.lang.violations.chat.profanity.processedMessage, response.getProcessedMessage()); - reportInfo.addKeyValue(Sentinel.lang.violations.chat.profanity.severity, response.getSeverity().toString()); + Node reportInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.reportInfoTitle); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.originalMessage, response.getOriginalMessage()); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.processedMessage, response.getProcessedMessage()); + reportInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.chat.profanity.severity, response.getSeverity().toString()); root.addChild(reportInfo); - Node actions = new Node(Sentinel.lang.violations.protections.actionNode.actionNodeTitle); - actions.addTextLine(Sentinel.lang.violations.chat.denyMessage); - if (response.isPunished()) actions.addTextLine(Sentinel.lang.violations.protections.actionNode.punishmentCommandsExecuted); + Node actions = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.actionNodeTitle); + actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.denyMessage); + if (response.isPunished()) actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.punishmentCommandsExecuted); root.addChild(actions); return root; @@ -74,6 +75,6 @@ public class ProfanityAction extends AbstractActionHandler { @Override protected boolean shouldWarnPlayer(ProfanityResponse response) { - return !Sentinel.mainConfig.chat.profanityFilter.silent; + return !Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.silent; } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityFilter.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityFilter.java index c07ddb1..516e8e4 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityFilter.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityFilter.java @@ -18,7 +18,7 @@ public class ProfanityFilter { ServerUtils.verbose("Anti Profanity Opening: Event is canceled."); } Player player = event.getPlayer(); - ProfanityResponse response = ProfanityResponse.generate(event); + ProfanityResponse response = new ProfanityResponse(null,null,null,null,null,false,false).generate(event); Severity severity = response.getSeverity(); ServerUtils.verbose("Response came back."); if (severity == null) return; @@ -33,7 +33,7 @@ public class ProfanityFilter { int newScore = previousScore + severity.getScore(); scoreMap.put(player.getUniqueId(), newScore); - if (newScore > Sentinel.mainConfig.chat.profanityFilter.punishScore || Severity.SLUR.equals(severity)) { + if (newScore > Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.punishScore || Severity.SLUR.equals(severity)) { response.setPunished(true); new ProfanityAction().run(response); return; @@ -46,7 +46,7 @@ public class ProfanityFilter { for (UUID uuid : scoreMap.keySet()) { int score = scoreMap.get(uuid); if (score > 0) { - score = score - Sentinel.mainConfig.chat.profanityFilter.scoreDecay; + score = score - Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.scoreDecay; scoreMap.put(uuid, Math.max(0, score)); } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.java index b40737e..ac9e812 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/ProfanityResponse.java @@ -1,9 +1,8 @@ package me.trouper.sentinel.server.functions.chatfilter.profanity; import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.data.Emojis; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; -import me.trouper.sentinel.server.functions.helpers.FilterHelpers; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.Emojis; import me.trouper.sentinel.server.functions.chatfilter.FilterResponse; import me.trouper.sentinel.server.functions.helpers.Report; import me.trouper.sentinel.utils.ServerUtils; @@ -11,6 +10,9 @@ import me.trouper.sentinel.utils.Text; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.entity.Player; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class ProfanityResponse implements FilterResponse { private AsyncChatEvent event; @@ -98,7 +100,7 @@ public class ProfanityResponse implements FilterResponse { } String message = LegacyComponentSerializer.legacySection().serialize(e.message()); - Report report = FalsePositiveReporting.initializeReport(message); + Report report = Sentinel.getInstance().getDirector().reportHandler.initializeReport(message); Severity severity = Severity.SAFE; ProfanityResponse response = new ProfanityResponse(e,message,null,report,severity,false,false); @@ -109,77 +111,78 @@ public class ProfanityResponse implements FilterResponse { // 1: String lowercasedText = text.toLowerCase(); response.getReport().getStepsTaken().put("Lowercased", lowercasedText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(lowercasedText,"", "")); + response.setProcessedMessage(highlightProfanity(lowercasedText,"", "")); ServerUtils.verbose("ProfanityFilter: Lowercased: " + lowercasedText); // 2: - String cleanedText = FilterHelpers.removeFalsePositives(lowercasedText); + String cleanedText = removeFalsePositives(lowercasedText); response.getReport().getStepsTaken().put("Remove False Positives", cleanedText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(cleanedText,"", "")); + response.setProcessedMessage(highlightProfanity(cleanedText,"", "")); ServerUtils.verbose(("ProfanityFilter: Removed False positives: " + cleanedText)); - response.setSeverity(FilterHelpers.checkSlur(cleanedText, Severity.LOW)); + response.setSeverity(checkProfanity(cleanedText, Severity.LOW)); if (response.getSeverity() != Severity.SAFE) { response.getReport().getStepsTaken().replace("Remove False Positives", "%s %s".formatted( - FilterHelpers.highlightProfanity(cleanedText,"||","||"), + highlightProfanity(cleanedText,"||","||"), Emojis.alarm)); return response; } // 4: - String convertedText = FilterHelpers.convertLeetSpeakCharacters(cleanedText); + String convertedText = convertLeetSpeakCharacters(cleanedText); response.getReport().getStepsTaken().put("Convert LeetSpeak", convertedText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(convertedText,"", "")); + response.setProcessedMessage(highlightProfanity(convertedText,"", "")); ServerUtils.verbose(("ProfanityFilter: Leet Converted: " + convertedText)); - response.setSeverity(FilterHelpers.checkSlur(convertedText, Severity.MEDIUM_LOW)); + response.setSeverity(checkProfanity(convertedText, Severity.MEDIUM_LOW)); if (response.getSeverity() != Severity.SAFE) { response.getReport().getStepsTaken().replace("Convert LeetSpeak", "%s %s".formatted( - FilterHelpers.highlightProfanity(cleanedText,"||","||"), + highlightProfanity(cleanedText,"||","||"), Emojis.alarm)); return response; } // 6: - String strippedText = FilterHelpers.stripSpecialCharacters(convertedText); + String strippedText = stripSpecialCharacters(convertedText); response.getReport().getStepsTaken().put("Remove Special Characters", strippedText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(strippedText,"", "")); + response.setProcessedMessage(highlightProfanity(strippedText,"", "")); ServerUtils.verbose(("ProfanityFilter: Specials Removed: " + strippedText)); - response.setSeverity(FilterHelpers.checkSlur(strippedText, Severity.MEDIUM)); + response.setSeverity(checkProfanity(strippedText, Severity.MEDIUM)); if (response.getSeverity() != Severity.SAFE) { response.getReport().getStepsTaken().replace("Remove Special Characters", "%s %s".formatted( - FilterHelpers.highlightProfanity(cleanedText,"||","||"), + highlightProfanity(cleanedText,"||","||"), Emojis.alarm)); return response; } // 8: - String simplifiedText = FilterHelpers.simplifyRepeatingLetters(strippedText); + String simplifiedText = simplifyRepeatingLetters(strippedText); response.getReport().getStepsTaken().put("Remove Repeats", simplifiedText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(simplifiedText,"", "")); + response.setProcessedMessage(highlightProfanity(simplifiedText,"", "")); ServerUtils.verbose(("ProfanityFilter: Removed Repeating: " + simplifiedText)); - response.setSeverity(FilterHelpers.checkSlur(simplifiedText, Severity.MEDIUM_HIGH)); + response.setSeverity(checkProfanity(simplifiedText, Severity.MEDIUM_HIGH)); if (response.getSeverity() != Severity.SAFE) { response.getReport().getStepsTaken().replace("Remove Repeats", "%s %s".formatted( - FilterHelpers.highlightProfanity(cleanedText,"||","||"), + highlightProfanity(cleanedText,"||","||"), Emojis.alarm)); return response; } // 10: - String finalText = FilterHelpers.removePeriodsAndSpaces(simplifiedText); + String finalText = removePeriodsAndSpaces(simplifiedText); response.getReport().getStepsTaken().put("Remove Punctuation", finalText); - response.setProcessedMessage(FilterHelpers.highlightProfanity(finalText,"", "")); + response.setProcessedMessage(highlightProfanity(finalText,"", "")); ServerUtils.verbose(("ProfanityFilter: Remove Punctuation: " + finalText)); - response.setSeverity(FilterHelpers.checkSlur(finalText, Severity.HIGH)); + response.setSeverity(checkProfanity(finalText, Severity.HIGH)); if (response.getSeverity() != Severity.SAFE) { response.getReport().getStepsTaken().replace("Remove Punctuation", "%s %s".formatted( - FilterHelpers.highlightProfanity(cleanedText,"||","||"), + highlightProfanity(cleanedText,"||","||"), Emojis.alarm)); + return response; } ServerUtils.verbose(("ProfanityFilter: Finished " + finalText)); @@ -188,4 +191,91 @@ public class ProfanityResponse implements FilterResponse { } return response; } + + private static Severity checkProfanity(String text, Severity backup) { + if (containsSlurs(text)) return Severity.SLUR; + if (containsSwears(text)) return backup; + return Severity.SAFE; + } + + private static boolean containsSwears(String text) { + ServerUtils.verbose("ProfanityFilter: Checking for swears"); + for (String swear : Sentinel.getInstance().getDirector().io.swearConfig.swears) { + if (text.contains(swear)) return true; + } + + Pattern pattern = Pattern.compile(Sentinel.getInstance().getDirector().io.swearConfig.regexSwears, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(text); + + return matcher.find() && Sentinel.getInstance().getDirector().io.swearConfig.useRegex; + } + + private static boolean containsSlurs(String text) { + ServerUtils.verbose("ProfanityFilter: Checking for slurs"); + for (String slur : Sentinel.getInstance().getDirector().io.strictConfig.strict) { + if (text.contains(slur)) return true; + } + + Pattern pattern = Pattern.compile(Sentinel.getInstance().getDirector().io.strictConfig.regexStrict, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(text); + + return matcher.find() && Sentinel.getInstance().getDirector().io.strictConfig.useRegex; + } + + private static String removeFalsePositives(String text) { + for (String falsePositive : Sentinel.getInstance().getDirector().io.fpConfig.swearWhitelist) { + text = text.replace(falsePositive, ""); + } + if (Sentinel.getInstance().getDirector().io.fpConfig.useRegex) text = text.replaceAll(Sentinel.getInstance().getDirector().io.fpConfig.regexWhitelist,""); + return text; + } + + private static String convertLeetSpeakCharacters(String text) { + text = Text.fromLeetString(text); + return text; + } + + private static String stripSpecialCharacters(String text) { + text = text.replaceAll("[^A-Za-z0-9.,!?;:'\"()\\[\\]{}]", "").trim(); + return text; + } + + private static String simplifyRepeatingLetters(String text) { + text = Text.replaceRepeatingLetters(text); + return text; + } + + private static String removePeriodsAndSpaces(String text) { + return text.replaceAll("[^A-Za-z0-9]", "").replace(" ", ""); + } + + private static String highlightProfanity(String text, String start, String end) { + String highlightedSwears = highlightSwears(fullSimplify(text), start, end); + return Text.color(highlightSlurs(highlightedSwears, start, end)); + } + + private static String highlightSwears(String text, String start, String end) { + for (String swear : Sentinel.getInstance().getDirector().io.swearConfig.swears) { + text = text.replace(swear, start + swear + end); + } + return text; + } + + private static String highlightSlurs(String text, String start, String end) { + for (String slur : Sentinel.getInstance().getDirector().io.strictConfig.strict) { + text = text.replace(slur, start + slur + end); + } + return text; + } + + private static String fullSimplify(String text) { + String lowercasedText = text.toLowerCase(); + String cleanedText = removeFalsePositives(lowercasedText); + String convertedText =convertLeetSpeakCharacters(cleanedText); + String strippedText = stripSpecialCharacters(convertedText); + String simplifiedText = simplifyRepeatingLetters(strippedText); + return removePeriodsAndSpaces(simplifiedText); + } + + } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.java index dbe2b2b..8cf7dc2 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/profanity/Severity.java @@ -3,13 +3,13 @@ package me.trouper.sentinel.server.functions.chatfilter.profanity; import me.trouper.sentinel.Sentinel; public enum Severity { - LOW(Sentinel.mainConfig.chat.profanityFilter.lowScore), - MEDIUM_LOW(Sentinel.mainConfig.chat.profanityFilter.mediumLowScore), - MEDIUM(Sentinel.mainConfig.chat.profanityFilter.mediumScore), - MEDIUM_HIGH(Sentinel.mainConfig.chat.profanityFilter.mediumHighScore), - HIGH(Sentinel.mainConfig.chat.profanityFilter.highScore), - REGEX(Sentinel.mainConfig.chat.profanityFilter.regexScore), - SLUR(Sentinel.mainConfig.chat.profanityFilter.highScore), + LOW(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.lowScore), + MEDIUM_LOW(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumLowScore), + MEDIUM(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumScore), + MEDIUM_HIGH(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumHighScore), + HIGH(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.highScore), + REGEX(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.regexScore), + SLUR(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.highScore), SAFE(0); private final int score; diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.java index c6a4792..0548fc2 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamAction.java @@ -2,6 +2,7 @@ package me.trouper.sentinel.server.functions.chatfilter.spam; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.server.functions.chatfilter.AbstractActionHandler; +import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import me.trouper.sentinel.utils.trees.HoverFormatter; @@ -13,7 +14,7 @@ public class SpamAction extends AbstractActionHandler { @Override public void punish(SpamResponse response) { - for (String spamPunishCommand : Sentinel.mainConfig.chat.spamFilter.punishCommands) { + for (String spamPunishCommand : Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishCommands) { ServerUtils.sendCommand(spamPunishCommand.replaceAll("%player%", response.getEvent().getPlayer().getName())); } } @@ -22,21 +23,21 @@ public class SpamAction extends AbstractActionHandler { public void staffWarning(SpamResponse report, Node tree) { String messageText = Text.prefix("&b&n%s&r &7%s &8(&4%s&7/&c%s&8)".formatted( report.getEvent().getPlayer().getName(), - report.isPunished() ? Sentinel.lang.violations.chat.spam.autoPunishNotification : Sentinel.lang.violations.chat.spam.preventNotification, + report.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.autoPunishNotification : Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.preventNotification, SpamFilter.heatMap.get(report.getEvent().getPlayer().getUniqueId()), - Sentinel.mainConfig.chat.spamFilter.punishHeat + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishHeat )); String hoverText = HoverFormatter.format(tree); - ServerUtils.forEachPlayer(player -> { + PlayerUtils.forEachPlayer(player -> { if (player.hasPermission("sentinel.chatfilter.spam.view")) player.sendMessage(Component.text(messageText).hoverEvent(Component.text(hoverText).asHoverEvent())); }); } @Override public void playerWarning(SpamResponse response) { - String message = Text.prefix(response.isPunished() ? Sentinel.lang.violations.chat.spam.autoPunishWarning : Sentinel.lang.violations.chat.spam.preventWarning) ; - String hoverText = Sentinel.lang.automatedActions.reportable; + String message = Text.prefix(response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.autoPunishWarning : Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.preventWarning) ; + String hoverText = Sentinel.getInstance().getDirector().io.lang.automatedActions.reportable; String command = "/sentinelcallback fpreport %s".formatted(response.getReport().getId()); response.getEvent().getPlayer().sendMessage(Component.text(message) .hoverEvent(Component.text(hoverText).asHoverEvent()) @@ -46,22 +47,22 @@ public class SpamAction extends AbstractActionHandler { @Override public Node buildTree(SpamResponse response) { Node root = new Node("Sentinel"); - root.addTextLine(Sentinel.lang.violations.chat.spam.treeTitle); + root.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.treeTitle); - Node playerInfo = new Node(Sentinel.lang.violations.protections.infoNode.playerInfo.formatted(response.getEvent().getPlayer().getName())); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.uuid, response.getEvent().getPlayer().getUniqueId().toString()); - playerInfo.addKeyValue(Sentinel.lang.violations.chat.spam.heat, "%s/%s".formatted(SpamFilter.heatMap.get(response.getEvent().getPlayer().getUniqueId()),Sentinel.mainConfig.chat.spamFilter.punishHeat)); + Node playerInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.playerInfo.formatted(response.getEvent().getPlayer().getName())); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.uuid, response.getEvent().getPlayer().getUniqueId().toString()); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.heat, "%s/%s".formatted(SpamFilter.heatMap.get(response.getEvent().getPlayer().getUniqueId()),Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishHeat)); root.addChild(playerInfo); - Node reportInfo = new Node(Sentinel.lang.violations.chat.spam.reportInfoTitle); - reportInfo.addField(Sentinel.lang.violations.chat.spam.previousMessage, response.getPreviousMessage()); - reportInfo.addField(Sentinel.lang.violations.chat.spam.currentMessage, response.getCurrentMessage()); - reportInfo.addKeyValue(Sentinel.lang.violations.chat.spam.similarity, "%s/%s".formatted((int) Math.round(response.getSimilarity()),Sentinel.mainConfig.chat.spamFilter.blockSimilarity)); + Node reportInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.reportInfoTitle); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.previousMessage, response.getPreviousMessage()); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.currentMessage, response.getCurrentMessage()); + reportInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.chat.spam.similarity, "%s/%s".formatted((int) Math.round(response.getSimilarity()),Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity)); root.addChild(reportInfo); - Node actions = new Node(Sentinel.lang.violations.protections.actionNode.actionNodeTitle); - actions.addTextLine(Sentinel.lang.violations.chat.denyMessage); - if (response.isPunished()) actions.addTextLine(Sentinel.lang.violations.protections.actionNode.punishmentCommandsExecuted); + Node actions = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.actionNodeTitle); + actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.denyMessage); + if (response.isPunished()) actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.punishmentCommandsExecuted); root.addChild(actions); return root; @@ -69,6 +70,6 @@ public class SpamAction extends AbstractActionHandler { @Override protected boolean shouldWarnPlayer(SpamResponse response) { - return !Sentinel.mainConfig.chat.spamFilter.silent; + return !Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.silent; } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamFilter.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamFilter.java index 7967bc0..82e02ed 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamFilter.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamFilter.java @@ -21,7 +21,7 @@ public class SpamFilter { } Player p = e.getPlayer(); String message = Text.removeFirstColor(LegacyComponentSerializer.legacySection().serialize(e.message())); - for (String whitelistedMessage : Sentinel.mainConfig.chat.spamFilter.whitelist) { + for (String whitelistedMessage : Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.whitelist) { if (whitelistedMessage.equalsIgnoreCase(message)) return; } int currentHeat = heatMap.getOrDefault(p.getUniqueId(),0); @@ -34,7 +34,7 @@ public class SpamFilter { ServerUtils.verbose("AntiSpam responded"); response.getReport().getStepsTaken().put("Response came back", "Heat to add: %s".formatted(addHeat)); - if (currentHeat > Sentinel.mainConfig.chat.spamFilter.punishHeat) { + if (currentHeat > Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishHeat) { response.setBlocked(true); response.getReport().getStepsTaken().put("Punished user", "Their final heat was %s".formatted(currentHeat)); response.setPunished(true); @@ -43,7 +43,7 @@ public class SpamFilter { return; } - if (currentHeat > Sentinel.mainConfig.chat.spamFilter.blockHeat) { + if (currentHeat > Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockHeat) { response.setBlocked(true); response.getReport().getStepsTaken().put("Blocked message", "Their heat is %s".formatted(currentHeat)); new SpamAction().run(response); @@ -51,7 +51,7 @@ public class SpamFilter { return; } - if (response.getSimilarity() > Sentinel.mainConfig.chat.spamFilter.blockSimilarity) { + if (response.getSimilarity() > Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity) { response.setBlocked(true); response.getReport().getStepsTaken().put("Blocked message", "The similarity was too high! %s".formatted(response.getSimilarity())); new SpamAction().run(response); @@ -69,7 +69,7 @@ public class SpamFilter { for (UUID p : heatMap.keySet()) { int heat = heatMap.getOrDefault(p,0); if (heat > 0) { - heat = heat - Sentinel.mainConfig.chat.spamFilter.heatDecay; + heat = heat - Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.heatDecay; heatMap.put(p, Math.max(0, heat)); } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.java index 96098e3..37d1156 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/spam/SpamResponse.java @@ -3,7 +3,7 @@ package me.trouper.sentinel.server.functions.chatfilter.spam; import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyComponentSerializer; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; +import me.trouper.sentinel.server.functions.helpers.ReportHandler; import me.trouper.sentinel.server.functions.chatfilter.FilterResponse; import me.trouper.sentinel.server.functions.helpers.Report; import me.trouper.sentinel.utils.MathUtils; @@ -40,7 +40,7 @@ public class SpamResponse implements FilterResponse { } String message = LegacyComponentSerializer.legacySection().serialize(e.message()); - Report report = FalsePositiveReporting.initializeReport(message); + Report report = Sentinel.getInstance().getDirector().reportHandler.initializeReport(message); message = Text.removeFirstColor(message); String previousMessage = lastMessageMap.getOrDefault(e.getPlayer().getUniqueId(),"/* Placeholder Message from Sentinel */"); @@ -52,25 +52,25 @@ public class SpamResponse implements FilterResponse { response.setSimilarity(similarity); report.getStepsTaken().put("Calculated Similarity: ","%s".formatted(similarity)); - int addHeat = Sentinel.mainConfig.chat.spamFilter.defaultGain; - if (similarity > Sentinel.mainConfig.chat.spamFilter.blockSimilarity) { - addHeat = Sentinel.mainConfig.chat.spamFilter.highGain; - response.getReport().getStepsTaken().put("Similarity is greater than %s%%".formatted(Sentinel.mainConfig.chat.spamFilter.blockSimilarity), "That is %s heat. (Auto-Block due to configured value)".formatted(addHeat)); + int addHeat = Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.defaultGain; + if (similarity > Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity) { + addHeat = Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.highGain; + response.getReport().getStepsTaken().put("Similarity is greater than %s%%".formatted(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity), "That is %s heat. (Auto-Block due to configured value)".formatted(addHeat)); response.setHeatAdded(addHeat); return response; } else if (similarity > 90) { - addHeat = Sentinel.mainConfig.chat.spamFilter.highGain; + addHeat = Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.highGain; response.getReport().getStepsTaken().put("Similarity is greater than 90%", "That is %s heat.".formatted(addHeat)); response.setHeatAdded(addHeat); return response; } else if (similarity > 50) { - addHeat = Sentinel.mainConfig.chat.spamFilter.mediumGain; + addHeat = Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.mediumGain; response.getReport().getStepsTaken().put("Similarity is greater than 50%", "That is %s heat.".formatted(addHeat)); response.setHeatAdded(addHeat); return response; } else if (similarity > 25) { response.getReport().getStepsTaken().put("Similarity is greater than 25%", "That is %s heat.".formatted(addHeat)); - addHeat = Sentinel.mainConfig.chat.spamFilter.lowGain; + addHeat = Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.lowGain; response.setHeatAdded(addHeat); return response; } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeAction.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeAction.java index a5c5243..2ad38e0 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeAction.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeAction.java @@ -2,6 +2,7 @@ package me.trouper.sentinel.server.functions.chatfilter.unicode; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.server.functions.chatfilter.AbstractActionHandler; +import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import me.trouper.sentinel.utils.trees.HoverFormatter; @@ -12,7 +13,7 @@ import net.kyori.adventure.text.event.ClickEvent; public class UnicodeAction extends AbstractActionHandler { @Override protected void punish(UnicodeResponse response) { - for (String punishCommand : Sentinel.mainConfig.chat.unicodeFilter.punishCommands) { + for (String punishCommand : Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punishCommands) { ServerUtils.sendCommand(punishCommand.replaceAll("%player%",response.getPlayer().getName())); } } @@ -21,19 +22,19 @@ public class UnicodeAction extends AbstractActionHandler { protected void staffWarning(UnicodeResponse response, Node tree) { String messageText = Text.prefix("&b&n%s&r &7%s".formatted( response.getPlayer().getName(), - response.isPunished() ? Sentinel.lang.violations.chat.unicode.autoPunishNotification : Sentinel.lang.violations.chat.unicode.preventNotification + response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.autoPunishNotification : Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.preventNotification )); String hoverText = HoverFormatter.format(tree); - ServerUtils.forEachPlayer(player -> { + PlayerUtils.forEachPlayer(player -> { if (player.hasPermission("sentinel.chatfilter.unicode.view")) player.sendMessage(Component.text(messageText).hoverEvent(Component.text(hoverText).asHoverEvent())); }); } @Override protected void playerWarning(UnicodeResponse response) { - String message = Text.prefix(response.isPunished() ? Sentinel.lang.violations.chat.unicode.autoPunishWarning : Sentinel.lang.violations.chat.unicode.preventWarning); - String hoverText = Sentinel.lang.automatedActions.reportable; + String message = Text.prefix(response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.autoPunishWarning : Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.preventWarning); + String hoverText = Sentinel.getInstance().getDirector().io.lang.automatedActions.reportable; String command = "/sentinelcallback fpreport %s".formatted(response.getReport().getId()); response.getPlayer().sendMessage(Component.text(message) .hoverEvent(Component.text(hoverText).asHoverEvent()) @@ -43,20 +44,20 @@ public class UnicodeAction extends AbstractActionHandler { @Override protected Node buildTree(UnicodeResponse response) { Node root = new Node("Sentinel"); - root.addTextLine(Sentinel.lang.violations.chat.unicode.treeTitle); + root.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.treeTitle); - Node playerInfo = new Node(Sentinel.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); + Node playerInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); root.addChild(playerInfo); - Node reportInfo = new Node(Sentinel.lang.violations.chat.unicode.reportInfoTitle); - reportInfo.addField(Sentinel.lang.violations.chat.originalMessage, response.getOriginalMessage()); - reportInfo.addField(Sentinel.lang.violations.chat.highlightedMessage, response.getHighlightedMessage()); + Node reportInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.chat.unicode.reportInfoTitle); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.originalMessage, response.getOriginalMessage()); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.highlightedMessage, response.getHighlightedMessage()); root.addChild(reportInfo); - Node actions = new Node(Sentinel.lang.violations.protections.actionNode.actionNodeTitle); - actions.addTextLine(Sentinel.lang.violations.chat.denyMessage); - if (response.isPunished()) actions.addTextLine(Sentinel.lang.violations.protections.actionNode.punishmentCommandsExecuted); + Node actions = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.actionNodeTitle); + actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.denyMessage); + if (response.isPunished()) actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.punishmentCommandsExecuted); root.addChild(actions); return root; @@ -64,6 +65,6 @@ public class UnicodeAction extends AbstractActionHandler { @Override protected boolean shouldWarnPlayer(UnicodeResponse response) { - return !Sentinel.mainConfig.chat.unicodeFilter.silent; + return !Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.silent; } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeResponse.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeResponse.java index 419350d..4fd216c 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeResponse.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/unicode/UnicodeResponse.java @@ -3,8 +3,7 @@ package me.trouper.sentinel.server.functions.chatfilter.unicode; import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyComponentSerializer; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.Emojis; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; +import me.trouper.sentinel.data.types.Emojis; import me.trouper.sentinel.server.functions.chatfilter.FilterResponse; import me.trouper.sentinel.server.functions.helpers.Report; import me.trouper.sentinel.utils.ServerUtils; @@ -39,11 +38,11 @@ public class UnicodeResponse implements FilterResponse { String message = LegacyComponentSerializer.legacySection().serialize(e.message()); message = Text.removeFirstColor(message); - Report report = FalsePositiveReporting.initializeReport(message); + Report report = Sentinel.getInstance().getDirector().reportHandler.initializeReport(message); UnicodeResponse response = new UnicodeResponse(e,message,message,report,false,false); - String disallowedRegex = Sentinel.mainConfig.chat.unicodeFilter.regex; + String disallowedRegex = Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.regex; ServerUtils.verbose("Regex: %s\nMessage: %s".formatted(disallowedRegex,message)); Pattern pattern = Pattern.compile(disallowedRegex, Pattern.CASE_INSENSITIVE); @@ -59,8 +58,8 @@ public class UnicodeResponse implements FilterResponse { response.getReport().getStepsTaken().replace("Anti-Unicode", "`%s` %s".formatted(message, Emojis.alarm)); response.setBlocked(true); - response.setPunished(Sentinel.mainConfig.chat.unicodeFilter.punished); - response.setHighlightedMessage(Text.regexHighlighter(message,Sentinel.mainConfig.chat.unicodeFilter.regex," > ", " < ")); + response.setPunished(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punished); + response.setHighlightedMessage(Text.regexHighlighter(message,Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.regex," > ", " < ")); } return response; diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlAction.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlAction.java index 9d71d10..6c27539 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlAction.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlAction.java @@ -2,6 +2,7 @@ package me.trouper.sentinel.server.functions.chatfilter.url; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.server.functions.chatfilter.AbstractActionHandler; +import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import me.trouper.sentinel.utils.trees.HoverFormatter; @@ -12,7 +13,7 @@ import net.kyori.adventure.text.event.ClickEvent; public class UrlAction extends AbstractActionHandler { @Override protected void punish(UrlResponse response) { - for (String punishCommand : Sentinel.mainConfig.chat.urlFilter.punishCommands) { + for (String punishCommand : Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punishCommands) { ServerUtils.sendCommand(punishCommand.replaceAll("%player%",response.getPlayer().getName())); } } @@ -21,19 +22,19 @@ public class UrlAction extends AbstractActionHandler { protected void staffWarning(UrlResponse response, Node tree) { String messageText = Text.prefix("&b&n%s&r &7%s".formatted( response.getPlayer().getName(), - response.isPunished() ? Sentinel.lang.violations.chat.url.autoPunishNotification : Sentinel.lang.violations.chat.url.preventNotification + response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.url.autoPunishNotification : Sentinel.getInstance().getDirector().io.lang.violations.chat.url.preventNotification )); String hoverText = HoverFormatter.format(tree); - ServerUtils.forEachPlayer(player -> { + PlayerUtils.forEachPlayer(player -> { if (player.hasPermission("sentinel.chatfilter.url.view")) player.sendMessage(Component.text(messageText).hoverEvent(Component.text(hoverText).asHoverEvent())); }); } @Override protected void playerWarning(UrlResponse response) { - String message = Text.prefix(response.isPunished() ? Sentinel.lang.violations.chat.url.autoPunishWarning : Sentinel.lang.violations.chat.url.preventWarning); - String hoverText = Sentinel.lang.automatedActions.reportable; + String message = Text.prefix(response.isPunished() ? Sentinel.getInstance().getDirector().io.lang.violations.chat.url.autoPunishWarning : Sentinel.getInstance().getDirector().io.lang.violations.chat.url.preventWarning); + String hoverText = Sentinel.getInstance().getDirector().io.lang.automatedActions.reportable; String command = "/sentinelcallback fpreport %s".formatted(response.getReport().getId()); response.getPlayer().sendMessage(Component.text(message) .hoverEvent(Component.text(hoverText).asHoverEvent()) @@ -43,20 +44,20 @@ public class UrlAction extends AbstractActionHandler { @Override protected Node buildTree(UrlResponse response) { Node root = new Node("Sentinel"); - root.addTextLine(Sentinel.lang.violations.chat.url.treeTitle); + root.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.url.treeTitle); - Node playerInfo = new Node(Sentinel.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); + Node playerInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.playerInfo.formatted(response.getPlayer().getName())); + playerInfo.addKeyValue(Sentinel.getInstance().getDirector().io.lang.violations.protections.infoNode.uuid, response.getPlayer().getUniqueId().toString()); root.addChild(playerInfo); - Node reportInfo = new Node(Sentinel.lang.violations.chat.url.reportInfoTitle); - reportInfo.addField(Sentinel.lang.violations.chat.originalMessage, response.getOriginalMessage()); - reportInfo.addField(Sentinel.lang.violations.chat.highlightedMessage, response.getHighlightedMessage()); + Node reportInfo = new Node(Sentinel.getInstance().getDirector().io.lang.violations.chat.url.reportInfoTitle); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.originalMessage, response.getOriginalMessage()); + reportInfo.addField(Sentinel.getInstance().getDirector().io.lang.violations.chat.highlightedMessage, response.getHighlightedMessage()); root.addChild(reportInfo); - Node actions = new Node(Sentinel.lang.violations.protections.actionNode.actionNodeTitle); - actions.addTextLine(Sentinel.lang.violations.chat.denyMessage); - if (response.isPunished()) actions.addTextLine(Sentinel.lang.violations.protections.actionNode.punishmentCommandsExecuted); + Node actions = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.actionNodeTitle); + actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.chat.denyMessage); + if (response.isPunished()) actions.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.punishmentCommandsExecuted); root.addChild(actions); return root; @@ -64,6 +65,6 @@ public class UrlAction extends AbstractActionHandler { @Override protected boolean shouldWarnPlayer(UrlResponse response) { - return !Sentinel.mainConfig.chat.urlFilter.silent; + return !Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.silent; } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlResponse.java b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlResponse.java index 10c4c64..8f7f75e 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlResponse.java +++ b/src/main/java/me/trouper/sentinel/server/functions/chatfilter/url/UrlResponse.java @@ -3,8 +3,7 @@ package me.trouper.sentinel.server.functions.chatfilter.url; import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyComponentSerializer; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.Emojis; -import me.trouper.sentinel.server.functions.helpers.FalsePositiveReporting; +import me.trouper.sentinel.data.types.Emojis; import me.trouper.sentinel.server.functions.chatfilter.FilterResponse; import me.trouper.sentinel.server.functions.helpers.Report; import me.trouper.sentinel.utils.ServerUtils; @@ -36,9 +35,9 @@ public class UrlResponse implements FilterResponse { } String message = LegacyComponentSerializer.legacySection().serialize(e.message()); - Report report = FalsePositiveReporting.initializeReport(message); + Report report = Sentinel.getInstance().getDirector().reportHandler.initializeReport(message); UrlResponse response = new UrlResponse(e,message,message,report,false,false); - for (String allowed : Sentinel.mainConfig.chat.urlFilter.whitelist) { + for (String allowed : Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.whitelist) { message = message.replaceAll(allowed,""); } @@ -46,7 +45,7 @@ public class UrlResponse implements FilterResponse { message )); - String urlRegex = Sentinel.mainConfig.chat.urlFilter.regex; + String urlRegex = Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.regex; Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(message); @@ -56,12 +55,12 @@ public class UrlResponse implements FilterResponse { )); if (matcher.find()) { - String highlighted = Text.regexHighlighter(message,Sentinel.mainConfig.chat.urlFilter.regex," > "," < "); + String highlighted = Text.regexHighlighter(message,Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.regex," > "," < "); ServerUtils.verbose("Caught URL: " + highlighted); response.getReport().getStepsTaken().replace("Anti-URL", "`%s` %s".formatted(highlighted, Emojis.alarm)); response.setBlocked(true); - response.setPunished(Sentinel.mainConfig.chat.urlFilter.punished); + response.setPunished(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punished); response.setHighlightedMessage(highlighted); } diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/AbstractViolation.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/AbstractViolation.java deleted file mode 100644 index 65979a4..0000000 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/AbstractViolation.java +++ /dev/null @@ -1,133 +0,0 @@ -package me.trouper.sentinel.server.functions.helpers; - -import io.github.itzispyder.pdk.events.CustomListener; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.utils.FileUtils; -import me.trouper.sentinel.utils.PlayerUtils; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import me.trouper.sentinel.utils.trees.ConsoleFormatter; -import me.trouper.sentinel.utils.trees.EmbedFormatter; -import me.trouper.sentinel.utils.trees.HoverFormatter; -import me.trouper.sentinel.utils.trees.Node; -import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; -import org.bukkit.block.Block; -import org.bukkit.block.CommandBlock; -import org.bukkit.command.Command; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - -public abstract class AbstractViolation implements CustomListener { - - public void runActions(String rootName, String rootNamePlayer, Node violationInfo, ActionConfiguration.Builder configuration) { - ActionConfiguration config = configuration.build(); - - Node root = new Node("Sentinel"); - root.addTextLine(rootName); - - if (config.getPlayer() != null) root.addChild(generatePlayerInfo(config.getPlayer())); - - root.addChild(violationInfo); - - root.addChild(configuration.getActionNode()); - - notifyTrusted(root,(rootNamePlayer == null || rootNamePlayer.isBlank()) ? rootName : rootNamePlayer); - if (configuration.isLoggedToDiscord()) EmbedFormatter.sendEmbed(EmbedFormatter.format(root)); - Sentinel.log.info(ConsoleFormatter.format(root)); - } - - public void notifyTrusted(Node root, String rootNamePlayer) { - ServerUtils.forEachPlayer(trusted -> { - if (PlayerUtils.isTrusted(trusted)) { - trusted.sendMessage(Component.text(Text.prefix(rootNamePlayer)).hoverEvent(Component.text(HoverFormatter.format(root)).asHoverEvent())); - } - }); - } - - public Node generatePlayerInfo(Player p) { - Node playerInfo = new Node(Sentinel.lang.violations.protections.infoNode.playerInfo); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.name, p.getName()); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.uuid, p.getUniqueId().toString()); - playerInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.operator, p.isOp() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - playerInfo.addField(Sentinel.lang.violations.protections.infoNode.locationField, Sentinel.lang.violations.protections.infoNode.locationFormat.formatted(Math.round(p.getX()), Math.round(p.getY()), Math.round(p.getZ()))); - - return playerInfo; - } - - public static Node generateBlockInfo(Block block) { - Node blockInfo = new Node(Sentinel.lang.violations.protections.infoNode.blockInfo); - blockInfo.addTextLine(Text.cleanName(block.getType().toString())); - blockInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.worldField,block.getWorld().getName()); - blockInfo.addField(Sentinel.lang.violations.protections.infoNode.blockLocationField,Sentinel.lang.violations.protections.infoNode.locationFormat.formatted(block.getX(), block.getY(), block.getZ())); - - return blockInfo; - } - - public Node generateCommandBlockInfo(CommandBlock commandBlock) { - Node commandBlockInfo = new Node(Sentinel.lang.violations.protections.infoNode.blockInfo); - commandBlockInfo.addTextLine(Text.cleanName(commandBlock.getType().toString())); - commandBlockInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.worldField,commandBlock.getWorld().getName()); - commandBlockInfo.addField(Sentinel.lang.violations.protections.infoNode.blockLocationField,Sentinel.lang.violations.protections.infoNode.locationFormat.formatted(commandBlock.getX(), commandBlock.getY(), commandBlock.getZ())); - - String command = commandBlock.getCommand(); - if (command == null || command.isBlank()) { - return commandBlockInfo; - } else if (command.length() <= 128) { - commandBlockInfo.addField(Sentinel.lang.violations.protections.infoNode.commandField, command); - } else { - commandBlockInfo.addField(Sentinel.lang.violations.protections.infoNode.commandTooLargeField, FileUtils.createCommandLog(command)); - } - - return commandBlockInfo; - } - - public Node generateMinecartInfo(Entity entity) { - Node minecartInfo = new Node(Sentinel.lang.violations.protections.infoNode.minecartInfo); - minecartInfo.addTextLine(Text.cleanName(entity.getType().toString())); - minecartInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.worldField,entity.getWorld().getName()); - minecartInfo.addField(Sentinel.lang.violations.protections.infoNode.cartLocationField,Sentinel.lang.violations.protections.infoNode.locationFormat.formatted(Math.round(entity.getX()), Math.round(entity.getY()), Math.round(entity.getZ()))); - - return minecartInfo; - } - - public Node generateItemInfo(ItemStack item) { - Node itemInfo = new Node(Sentinel.lang.violations.protections.infoNode.itemInfo); - itemInfo.addTextLine(Text.cleanName(item.getType().toString())); - itemInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.hasMeta,item.hasItemMeta() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - if (item.hasItemMeta()) { - itemInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.hasName,item.getItemMeta().hasCustomName() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - itemInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.hasLore,item.getItemMeta().hasLore() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - itemInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.hasAttributes,item.getItemMeta().hasAttributeModifiers() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - itemInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.hasEnchants,item.getItemMeta().hasEnchants() ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - itemInfo.addField(Sentinel.lang.violations.protections.infoNode.nbtStored, FileUtils.createNBTLog(item)); - } - - return itemInfo; - } - - public Node generateCommandInfo(String command, Player executor) { - Node commandInfo = new Node(Sentinel.lang.violations.protections.infoNode.commandInfo); - String name = command.split(" ")[0].substring(1); - ServerUtils.verbose("Command Name: " + name); - Command executed = Bukkit.getServer().getCommandMap().getCommand(name); - - commandInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.name,name); - if (command.length() <= 128) { - commandInfo.addField(Sentinel.lang.violations.protections.infoNode.commandField, command); - } else { - commandInfo.addField(Sentinel.lang.violations.protections.infoNode.commandTooLargeField, FileUtils.createCommandLog(command)); - } - if (executed == null || executed.getPermission() == null) return commandInfo; - commandInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.permissionRequired,executed.getPermission()); - commandInfo.addKeyValue(Sentinel.lang.violations.protections.infoNode.permissionSatisfied,executor.hasPermission(executed.getPermission()) ? Sentinel.lang.generic.yes : Sentinel.lang.generic.no); - - return commandInfo; - } -} diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/ActionConfiguration.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/ActionConfiguration.java index 5408505..fc2eb15 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/ActionConfiguration.java +++ b/src/main/java/me/trouper/sentinel/server/functions/helpers/ActionConfiguration.java @@ -1,10 +1,12 @@ package me.trouper.sentinel.server.functions.helpers; import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.SerialLocation; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.trees.Node; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; @@ -18,7 +20,9 @@ public class ActionConfiguration { private Cancellable event; private boolean cancel; private Block block; + private Entity entity; private boolean destroyBlock; + private boolean removeEntity; private boolean restoreBlock; private boolean punish; private List punishmentCommands; @@ -31,7 +35,9 @@ public class ActionConfiguration { this.event = builder.event; this.cancel = builder.cancel; this.block = builder.block; + this.entity = builder.entity; this.destroyBlock = builder.destroyBlock; + this.removeEntity = builder.removeEntity; this.restoreBlock = builder.restoreBlock; this.punish = builder.punish; this.punishmentCommands = builder.punishmentCommands; @@ -80,6 +86,14 @@ public class ActionConfiguration { this.block = block; } + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + } + public boolean isDestroyBlock() { return destroyBlock; } @@ -88,6 +102,14 @@ public class ActionConfiguration { this.destroyBlock = destroyBlock; } + public void setRemoveEntity(boolean removeEntity) { + this.removeEntity = removeEntity; + } + + public boolean getRemoveEntity() { + return removeEntity; + } + public boolean isRestoreBlock() { return restoreBlock; } @@ -134,12 +156,14 @@ public class ActionConfiguration { private Cancellable event; private boolean cancel; private Block block; + private Entity entity; private boolean destroyBlock; + private boolean removeEntity; private boolean restoreBlock; private boolean punish; private List punishmentCommands = new ArrayList<>(); private boolean logToDiscord; - private Node actionNode = new Node(Sentinel.lang.violations.protections.actionNode.actionNodeTitle); + private Node actionNode = new Node(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.actionNodeTitle); private List> actions = new ArrayList<>(); @@ -156,7 +180,7 @@ public class ActionConfiguration { if (config.player != null) { config.player.setOp(false); } - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.userDeoped); + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.userDeoped); }); return this; } @@ -174,7 +198,7 @@ public class ActionConfiguration { if (config.event != null) { config.event.setCancelled(true); } - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.eventCancelled); + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.eventCancelled); }); return this; } @@ -191,7 +215,7 @@ public class ActionConfiguration { config.destroyBlock = destroyBlock; if (config.block != null) { config.block.setType(Material.AIR); - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.destroyedBlock); + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.destroyedBlock); } }); return this; @@ -202,16 +226,33 @@ public class ActionConfiguration { actions.add(config -> { config.restoreBlock = restoreBlock; if (config.block != null) { - if (CBWhitelistManager.restore(config.block.getLocation())) { - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.restore); + if (Sentinel.getInstance().getDirector().whitelistManager.getFromWhitelist(config.block.getLocation()) != null && Sentinel.getInstance().getDirector().whitelistManager.getFromWhitelist(config.block.getLocation()).restore()) { + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.restore); } else { - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.restoreFailed); + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.restoreFailed); } } }); return this; } + public Builder setEntity(Entity entity) { + this.entity = entity; + actions.add(config -> config.entity = entity); + return this; + } + + public Builder removeEntity(boolean removeEntity) { + this.removeEntity = removeEntity; + actions.add(config -> { + config.removeEntity = removeEntity; + if (config.entity != null) { + entity.remove(); + } + }); + return this; + } + public Builder punish(boolean punish) { this.punish = punish; actions.add(config -> config.punish = punish); @@ -226,7 +267,7 @@ public class ActionConfiguration { for (String cmd : punishmentCommands) { ServerUtils.sendCommand(cmd.replaceAll("%player%", config.player.getName())); } - config.actionNode.addTextLine(Sentinel.lang.violations.protections.actionNode.punishmentCommandsExecuted); + config.actionNode.addTextLine(Sentinel.getInstance().getDirector().io.lang.violations.protections.actionNode.punishmentCommandsExecuted); } }); return this; diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/CBWhitelistManager.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/CBWhitelistManager.java index 3a7d125..b8edf1a 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/CBWhitelistManager.java +++ b/src/main/java/me/trouper/sentinel/server/functions/helpers/CBWhitelistManager.java @@ -1,185 +1,166 @@ package me.trouper.sentinel.server.functions.helpers; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.types.WhitelistedBlock; +import me.trouper.sentinel.data.types.SerialLocation; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.server.events.admin.WandEvents; +import me.trouper.sentinel.data.types.Selection; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.block.Block; import org.bukkit.block.CommandBlock; +import org.bukkit.block.data.Directional; +import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.CommandMinecart; import org.bukkit.persistence.PersistentDataType; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; public class CBWhitelistManager { - public static Set autoWhitelist = new HashSet<>(); + public Set autoWhitelist = new HashSet<>(); - public static void add(CommandBlock cb, UUID owner) { - ServerUtils.verbose("Adding a command block to the whitelist."); - boolean alwaysActive = getNBTBoolean(cb, "auto"); - WhitelistedBlock wb = new WhitelistedBlock(owner.toString(),WhitelistedBlock.serialize(cb.getLocation()),getType(cb),alwaysActive,cb.getCommand()); - - Location wbloc = WhitelistedBlock.fromSerialized(wb.loc()); - - remove(wbloc); - - Sentinel.whitelist.whitelistedCMDBlocks.add(wb); - Sentinel.whitelist.save(); - if (Bukkit.getPlayer(owner) != null && !Bukkit.getPlayer(owner).isOnline()) return; - Bukkit.getPlayer(owner).sendMessage(Text.prefix("Successfully whitelisted a &b" + Text.cleanName(cb.getType().toString()) + "&7 with the command &a" + cb.getCommand() + "&7.")); - } - - public static void remove(Location where) { - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - Location cbl = WhitelistedBlock.fromSerialized(cb.loc()); - if (cbl.distance(where) < 0.5) { - Sentinel.whitelist.whitelistedCMDBlocks.remove(cb); - } - } - - Sentinel.whitelist.save(); - } - - public static boolean canRun(Block b) { - CommandBlock test = (CommandBlock) b.getState(); - String command = test.getCommand(); - boolean alwaysActive = getNBTBoolean(test, "auto"); - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - if (!(b.getLocation().distance(WhitelistedBlock.fromSerialized(cb.loc())) < 0.5)) continue; - if (cb.active() != alwaysActive) return false; - if (!cb.command().equals(command)) return false; - if (!cb.type().equals(getType(test))) return false; - return PlayerUtils.isTrusted(cb.owner()); - } - return false; - } - - public static WhitelistedBlock get(Location where) { - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - Location cbl = WhitelistedBlock.fromSerialized(cb.loc()); - if (cbl.distance(where) < 0.5) { - return cb; - } - } - return null; - } - - public static int clearAll() { - int total = 0; - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - Location remove = WhitelistedBlock.fromSerialized(cb.loc()); - remove(remove); - remove.getBlock().setType(Material.AIR); - total++; - } - return total; - } - - public static int clearAll(UUID who) { - int total = 0; - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - if (!cb.owner().equals(who.toString())) continue; - Location remove = WhitelistedBlock.fromSerialized(cb.loc()); - remove(remove); - remove.getBlock().setType(Material.AIR); - total++; - } - return total; - } - - public static int restoreAll() { - int total = 0; - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++; - } - return total; - } - - public static int restoreAll(UUID who) { - int total = 0; - for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) { - if (!cb.owner().equals(who.toString())) continue; - if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++; - } - return total; - } - - - public static boolean restore(Location where) { - WhitelistedBlock wb = get(where); - if (wb == null) { - ServerUtils.verbose("No whitelisted command block found at the specified location."); - return false; - } - - Block block = where.getBlock(); - block.setType(getBlockType(wb.type())); - if (!(block.getState() instanceof CommandBlock)) { - ServerUtils.verbose("Block at the location was not a command block (You shouldn't be seeing this. Report it)."); - return false; - } - - CommandBlock cb = (CommandBlock) block.getState(); - cb.setCommand(wb.command()); - cb.setType(getBlockType(wb.type())); - setNBTBoolean(cb, "auto", wb.active()); - - cb.update(); - ServerUtils.verbose("Command block at " + where.toString() + " has been restored."); - return true; - } - - public static String getType(CommandBlock cb) { - switch (cb.getType()) { - case COMMAND_BLOCK -> { - return "impulse"; - } - case REPEATING_COMMAND_BLOCK -> { - return "repeat"; - } - case CHAIN_COMMAND_BLOCK -> { - return "chain"; - } - } - return null; - } - - private static Material getBlockType(String type) { - return switch (type) { - case "impulse" -> Material.COMMAND_BLOCK; - case "repeat" -> Material.REPEATING_COMMAND_BLOCK; - case "chain" -> Material.CHAIN_COMMAND_BLOCK; - default -> throw new IllegalArgumentException("Unknown command block type: " + type); - }; - } - - private static void setNBTBoolean(CommandBlock cmdBlock, String key, boolean value) { - cmdBlock.getPersistentDataContainer().set( - getKey(key), - PersistentDataType.BYTE, - value ? (byte) 1 : (byte) 0 + public CommandBlockHolder generateHolder(UUID owner, CommandMinecart cm) { + return new CommandBlockHolder(owner.toString(), + SerialLocation.uuidToLocation(cm.getUniqueId()), + "minecart", + cm.getType().name(), + false, + false, + cm.getCommand() ); } - - private static boolean getNBTBoolean(CommandBlock cmdBlock, String key) { - return cmdBlock.getPersistentDataContainer().has( - getKey(key), - PersistentDataType.BYTE - ) && cmdBlock.getPersistentDataContainer().get( - getKey(key), - PersistentDataType.BYTE - ) == 1; + public CommandBlockHolder generateHolder(UUID owner, CommandBlock cb) { + return new CommandBlockHolder(owner.toString(), + SerialLocation.translate(cb.getLocation()), + serializeFacing(cb.getBlock()), + serializeType(cb), + isAuto(cb), + isConditional(cb), + cb.getCommand() + ); } - private static NamespacedKey getKey(String key) { - return new NamespacedKey(Sentinel.getInstance(), key); + public void removeSelectionFromWhitelist(Player player) { + Selection selection = WandEvents.selections.get(player.getUniqueId()); + if (selection == null || !selection.isComplete()) { + player.sendMessage(Text.prefix("You must set 2 points first.")); + return; + } + AtomicInteger number = new AtomicInteger(); + selection.forEachBlock(block -> { + if (block.getType().equals(Material.COMMAND_BLOCK) || block.getType().equals(Material.REPEATING_COMMAND_BLOCK) || block.getType().equals(Material.CHAIN_COMMAND_BLOCK)) { + generateHolder(player.getUniqueId(),(CommandBlock) block.getState()).removeFromWhitelist(); + number.getAndIncrement(); + } + }); + + player.sendMessage(Text.prefix("Removed all &b%s&7 command blocks from the whitelist in your selection.".formatted(number.get()))); + } + + public void deleteSelection(Player player) { + Selection selection = WandEvents.selections.get(player.getUniqueId()); + if (selection == null || !selection.isComplete()) { + player.sendMessage(Text.prefix("You must set 2 points first.")); + return; + } + AtomicInteger number = new AtomicInteger(); + selection.forEachBlock(block -> { + if (block.getType().equals(Material.COMMAND_BLOCK) || block.getType().equals(Material.REPEATING_COMMAND_BLOCK) || block.getType().equals(Material.CHAIN_COMMAND_BLOCK)) { + generateHolder(player.getUniqueId(),(CommandBlock) block.getState()).destroy(); + number.getAndIncrement(); + } + }); + + player.sendMessage(Text.prefix("Deleted all &b%s&7 command blocks from the whitelist in your selection.".formatted(number.get()))); + } + + public void addSelectionToWhitelist(Player player) { + Selection selection = WandEvents.selections.get(player.getUniqueId()); + if (selection == null || !selection.isComplete()) { + player.sendMessage(Text.prefix("You must set 2 points first.")); + return; + } + + AtomicInteger number = new AtomicInteger(); + selection.forEachBlock(block -> { + if (ServerUtils.isCommandBlock(block)) { + CommandBlock cb = (CommandBlock) block.getState(); + generateHolder(player.getUniqueId(),cb).addToWhitelist(); + number.getAndIncrement(); + } + }); + + player.sendMessage(Text.prefix("Whitelisted all &b%s&7 command blocks in your selection.".formatted(number.get()))); + } + + public int clearAll() { + int total = 0; + for (CommandBlockHolder cb : Sentinel.getInstance().getDirector().io.commandBlocks.holders) { + cb.removeFromWhitelist(); + total++; + + if (cb.loc().isUUID()) continue; + Location remove = SerialLocation.translate(cb.loc()); + remove.getBlock().setType(Material.AIR); + } + return total; + } + + public int clearAll(UUID who) { + int total = 0; + for (CommandBlockHolder cb : Sentinel.getInstance().getDirector().io.commandBlocks.holders) { + if (!cb.owner().equals(who.toString())) continue; + cb.removeFromWhitelist(); + total++; + + if (cb.loc().isUUID()) continue; + Location remove = SerialLocation.translate(cb.loc()); + remove.getBlock().setType(Material.AIR); + } + return total; + } + + public int restoreAll() { + int total = 0; + for (CommandBlockHolder cb : Sentinel.getInstance().getDirector().io.commandBlocks.holders) { + if (cb.isWhitelisted() && cb.restore()) total++; + } + return total; + } + + public int restoreAll(UUID who) { + int total = 0; + for (CommandBlockHolder cb : Sentinel.getInstance().getDirector().io.commandBlocks.holders) { + if (!cb.owner().equals(who.toString())) continue; + if (cb.isWhitelisted() && cb.restore()) total++; + } + return total; + } + + public String serializeFacing(Block block) { + if (block.getBlockData() instanceof Directional directional) { + return directional.getFacing().name(); + } + return "UNKNOWN"; + } + + public String serializeType(CommandBlock cb) { + return cb.getType().name(); + } + + public boolean isAuto(CommandBlock cb) { + return cb.getPersistentDataContainer().getOrDefault(Sentinel.getInstance().getNamespace("auto"), PersistentDataType.BYTE,(byte) 0) == (byte) 1; + } + + public boolean isConditional(CommandBlock cb) { + return cb.getBlock().getBlockData() instanceof org.bukkit.block.data.type.CommandBlock cbs && cbs.isConditional(); } } diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/FilterHelpers.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/FilterHelpers.java deleted file mode 100644 index f5ae2ff..0000000 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/FilterHelpers.java +++ /dev/null @@ -1,107 +0,0 @@ -package me.trouper.sentinel.server.functions.helpers; - -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.functions.chatfilter.profanity.Severity; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class FilterHelpers { - - public static Severity checkSlur(String text, Severity backup) { - if (containsSlurs(text)) return Severity.SLUR; - if (containsSwears(text)) return backup; - return Severity.SAFE; - } - - public static boolean containsSwears(String text) { - ServerUtils.verbose("ProfanityFilter: Checking for swears"); - for (String swear : Sentinel.swearConfig.swears) { - if (text.contains(swear)) return true; - } - - Pattern pattern = Pattern.compile(Sentinel.swearConfig.regexSwears, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(text); - - return matcher.find() && Sentinel.swearConfig.useRegex; - } - - public static boolean containsSlurs(String text) { - ServerUtils.verbose("ProfanityFilter: Checking for slurs"); - for (String slur : Sentinel.strictConfig.strict) { - if (text.contains(slur)) return true; - } - - Pattern pattern = Pattern.compile(Sentinel.strictConfig.regexStrict, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(text); - - return matcher.find() && Sentinel.strictConfig.useRegex; - } - - public static String removeFalsePositives(String text) { - for (String falsePositive : Sentinel.fpConfig.swearWhitelist) { - text = text.replace(falsePositive, ""); - } - text = text.replaceAll(Sentinel.fpConfig.regexWhitelist,""); - return text; - } - - public static String convertLeetSpeakCharacters(String text) { - text = Text.fromLeetString(text); - return text; - } - - public static String stripSpecialCharacters(String text) { - text = text.replaceAll("[^A-Za-z0-9.,!?;:'\"()\\[\\]{}]", "").trim(); - return text; - } - - public static String simplifyRepeatingLetters(String text) { - text = Text.replaceRepeatingLetters(text); - return text; - } - - public static String removePeriodsAndSpaces(String text) { - return text.replaceAll("[^A-Za-z0-9]", "").replace(" ", ""); - } - - public static String highlightProfanity(String text, String start, String end) { - String highlightedSwears = highlightSwears(fullSimplify(text), start, end); - return Text.color(highlightSlurs(highlightedSwears, start, end)); - } - - private static String highlightSwears(String text, String start, String end) { - for (String swear : Sentinel.swearConfig.swears) { - text = text.replace(swear, start + swear + end); - } - return text; - } - - private static String highlightSlurs(String text, String start, String end) { - for (String slur : Sentinel.strictConfig.strict) { - text = text.replace(slur, start + slur + end); - } - return text; - } - - public static String fullSimplify(String text) { - String lowercasedText = text.toLowerCase(); - String cleanedText = FilterHelpers.removeFalsePositives(lowercasedText); - String convertedText = FilterHelpers.convertLeetSpeakCharacters(cleanedText); - String strippedText = FilterHelpers.stripSpecialCharacters(convertedText); - String simplifiedText = FilterHelpers.simplifyRepeatingLetters(strippedText); - return FilterHelpers.removePeriodsAndSpaces(simplifiedText); - } - - public static void restrictMessage(AsyncChatEvent event, boolean silent) { - if (silent) { - event.viewers().clear(); - event.viewers().add(event.getPlayer()); - } else { - event.setCancelled(true); - } - } -} diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/Message.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/MessageHandler.java similarity index 57% rename from src/main/java/me/trouper/sentinel/server/functions/helpers/Message.java rename to src/main/java/me/trouper/sentinel/server/functions/helpers/MessageHandler.java index a4896f4..82a2242 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/Message.java +++ b/src/main/java/me/trouper/sentinel/server/functions/helpers/MessageHandler.java @@ -5,7 +5,7 @@ import io.papermc.paper.chat.ChatRenderer; import io.papermc.paper.event.player.AsyncChatEvent; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.server.commands.SentinelCommand; -import me.trouper.sentinel.server.events.ChatEvent; +import me.trouper.sentinel.server.events.violations.players.ChatEvent; import net.kyori.adventure.chat.SignedMessage; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; @@ -13,27 +13,27 @@ import org.bukkit.entity.Player; import java.util.*; -public class Message { - public static final Map replyMap = new HashMap<>(); - public static void messagePlayer(Player sender, Player receiver, String message) { +public class MessageHandler { + public final Map replyMap = new HashMap<>(); + public void messagePlayer(Player sender, Player receiver, String message) { AsyncChatEvent checkEvent = new AsyncChatEvent(true,sender, new HashSet<>(Arrays.asList(receiver, sender)), ChatRenderer.defaultRenderer(),Component.text(message),Component.text(message), SignedMessage.system(message,Component.text(message))); if (checkEvent.isCancelled()) return; new ChatEvent().handleEvent(checkEvent); if (checkEvent.isCancelled()) return; - sender.sendMessage(Sentinel.lang.playerInteraction.messageSent.formatted(receiver.getName(),message)); - receiver.sendMessage(Sentinel.lang.playerInteraction.messageReceived.formatted(sender.getName(),message)); + sender.sendMessage(Sentinel.getInstance().getDirector().io.lang.playerInteraction.messageSent.formatted(receiver.getName(),message)); + receiver.sendMessage(Sentinel.getInstance().getDirector().io.lang.playerInteraction.messageReceived.formatted(sender.getName(),message)); replyMap.put(receiver.getUniqueId(),sender.getUniqueId()); sendSpy(sender,receiver,message); } - public static void sendSpy(Player sender, Player receiver, String message) { + public void sendSpy(Player sender, Player receiver, String message) { ServerUtils.forEachPlayer(player -> { if (SentinelCommand.spyMap.getOrDefault(player.getUniqueId(),false)) { TextComponent notification = Component - .text(Sentinel.lang.socialSpy.spyMessage.formatted(sender.getName(),receiver.getName())) - .hoverEvent(Component.text(Sentinel.lang.socialSpy.spyMessageHover.formatted(sender.getName(),receiver.getName(),message))); + .text(Sentinel.getInstance().getDirector().io.lang.socialSpy.spyMessage.formatted(sender.getName(),receiver.getName())) + .hoverEvent(Component.text(Sentinel.getInstance().getDirector().io.lang.socialSpy.spyMessageHover.formatted(sender.getName(),receiver.getName(),message))); player.sendMessage(notification); } }); diff --git a/src/main/java/me/trouper/sentinel/server/functions/helpers/FalsePositiveReporting.java b/src/main/java/me/trouper/sentinel/server/functions/helpers/ReportHandler.java similarity index 81% rename from src/main/java/me/trouper/sentinel/server/functions/helpers/FalsePositiveReporting.java rename to src/main/java/me/trouper/sentinel/server/functions/helpers/ReportHandler.java index 329874f..c3da9d2 100644 --- a/src/main/java/me/trouper/sentinel/server/functions/helpers/FalsePositiveReporting.java +++ b/src/main/java/me/trouper/sentinel/server/functions/helpers/ReportHandler.java @@ -2,8 +2,8 @@ package me.trouper.sentinel.server.functions.helpers; import io.github.itzispyder.pdk.utils.SchedulerUtils; import io.github.itzispyder.pdk.utils.discord.DiscordEmbed; -import me.trouper.sentinel.data.Emojis; -import me.trouper.sentinel.utils.Randomizer; +import me.trouper.sentinel.data.types.Emojis; +import me.trouper.sentinel.utils.Random; import me.trouper.sentinel.utils.trees.EmbedFormatter; import org.bukkit.entity.Player; @@ -11,11 +11,11 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; -public class FalsePositiveReporting { - public static Map reports = new HashMap<>(); +public class ReportHandler { + public Map reports = new HashMap<>(); - public static Report initializeReport(String message) { - final long reportID = Randomizer.generateID(); + public Report initializeReport(String message) { + final long reportID = Random.generateID(); LinkedHashMap steps = new LinkedHashMap<>(); steps.put("Original Message", "`%s`".formatted(message)); @@ -25,7 +25,7 @@ public class FalsePositiveReporting { return new Report(reportID,message,steps); } - public static void sendReport(Player sender, Report report) { + public void sendReport(Player sender, Report report) { DiscordEmbed.Builder embed = DiscordEmbed.create() .author(new DiscordEmbed.Author("Anti-Swear False Positive","",null)) .title("A player has reported a false positive") diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/AbstractCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/AbstractCheck.java new file mode 100644 index 0000000..97f49cc --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/AbstractCheck.java @@ -0,0 +1,10 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.ServerUtils; + +import java.util.Arrays; + +public abstract class AbstractCheck { + public abstract boolean passes(T input); +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EnchantmentCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EnchantmentCheck.java new file mode 100644 index 0000000..6ad5d4d --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EnchantmentCheck.java @@ -0,0 +1,122 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Map; + +import static org.bukkit.enchantments.Enchantment.MENDING; + +public class EnchantmentCheck { + + public boolean hasIllegalEnchants(ItemStack item) { + ServerUtils.verbose("Checking item for illegal enchants: ", item.getType().name()); + if (item.hasItemMeta() && item.getItemMeta().hasEnchants()) { + ItemMeta meta = item.getItemMeta(); + Map enchantments = meta.getEnchants(); + for (Map.Entry entry : enchantments.entrySet()) { + Enchantment enchantment = entry.getKey(); + int level = entry.getValue(); + if (level > Sentinel.getInstance().getDirector().io.nbtConfig.globalMaxEnchant || isOverLimit(enchantment, level)) { + return true; + } + } + } + return false; + } + + public static boolean isOverLimit(Enchantment enchantment, int level) { + int maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.globalMaxEnchant; + + if (enchantment.equals(MENDING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxMending; + } else if (enchantment.equals(Enchantment.UNBREAKING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxUnbreaking; + } else if (enchantment.equals(Enchantment.VANISHING_CURSE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxCurseOfVanishing; + } else if (enchantment.equals(Enchantment.BINDING_CURSE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxCurseOfBinding; + } else if (enchantment.equals(Enchantment.AQUA_AFFINITY)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxAquaAffinity; + } else if (enchantment.equals(Enchantment.PROTECTION)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxProtection; + } else if (enchantment.equals(Enchantment.BLAST_PROTECTION)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxBlastProtection; + } else if (enchantment.equals(Enchantment.DEPTH_STRIDER)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxDepthStrider; + } else if (enchantment.equals(Enchantment.FEATHER_FALLING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFeatherFalling; + } else if (enchantment.equals(Enchantment.FIRE_PROTECTION)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFireProtection; + } else if (enchantment.equals(Enchantment.FROST_WALKER)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFrostWalker; + } else if (enchantment.equals(Enchantment.PROJECTILE_PROTECTION)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxProjectileProtection; + } else if (enchantment.equals(Enchantment.RESPIRATION)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxRespiration; + } else if (enchantment.equals(Enchantment.SOUL_SPEED)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSoulSpeed; + } else if (enchantment.equals(Enchantment.THORNS)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxThorns; + } else if (enchantment.equals(Enchantment.SWEEPING_EDGE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSweepingEdge; + } else if (enchantment.equals(Enchantment.SWIFT_SNEAK)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSwiftSneak; + } else if (enchantment.equals(Enchantment.BANE_OF_ARTHROPODS)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxBaneOfArthropods; + } else if (enchantment.equals(Enchantment.FIRE_ASPECT)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFireAspect; + } else if (enchantment.equals(Enchantment.LOOTING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxLooting; + } else if (enchantment.equals(Enchantment.IMPALING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxImpaling; + } else if (enchantment.equals(Enchantment.KNOCKBACK)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxKnockback; + } else if (enchantment.equals(Enchantment.SHARPNESS)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSharpness; + } else if (enchantment.equals(Enchantment.SMITE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSmite; + } else if (enchantment.equals(Enchantment.CHANNELING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxChanneling; + } else if (enchantment.equals(Enchantment.FLAME)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFlame; + } else if (enchantment.equals(Enchantment.INFINITY)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxInfinity; + } else if (enchantment.equals(Enchantment.LOYALTY)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxLoyalty; + } else if (enchantment.equals(Enchantment.RIPTIDE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxRiptide; + } else if (enchantment.equals(Enchantment.MULTISHOT)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxMultishot; + } else if (enchantment.equals(Enchantment.PIERCING)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxPiercing; + } else if (enchantment.equals(Enchantment.POWER)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxPower; + } else if (enchantment.equals(Enchantment.PUNCH)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxPunch; + } else if (enchantment.equals(Enchantment.QUICK_CHARGE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxQuickCharge; + } else if (enchantment.equals(Enchantment.EFFICIENCY)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxEfficiency; + } else if (enchantment.equals(Enchantment.FORTUNE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxFortune; + } else if (enchantment.equals(Enchantment.LUCK_OF_THE_SEA)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxLuckOfTheSea; + } else if (enchantment.equals(Enchantment.LURE)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxLure; + } else if (enchantment.equals(Enchantment.SILK_TOUCH)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxSilkTouch; + } else if (enchantment.equals(Enchantment.BREACH)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxBreach; + } else if (enchantment.equals(Enchantment.DENSITY)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxDensity; + } else if (enchantment.equals(Enchantment.WIND_BURST)) { + maxLevel = Sentinel.getInstance().getDirector().io.nbtConfig.maxWindBurst; + } + + return level > maxLevel; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntityCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntityCheck.java new file mode 100644 index 0000000..37ade6a --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntityCheck.java @@ -0,0 +1,74 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import de.tr7zw.changeme.nbtapi.NBT; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.InventoryUtils; +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.Mob; +import org.bukkit.entity.Villager; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.MerchantRecipe; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class EntityCheck extends AbstractCheck { + + @Override + public boolean passes(Entity entity) { + if (entity instanceof Item itemEntity) { + if (!new ItemCheck().passes(itemEntity.getItemStack())) { + ServerUtils.verbose("Entity failed check: Item not allowed."); + return false; + } + } + Inventory inv = InventoryUtils.getInventory(entity); + if (inv != null && !new InventoryCheck().passes(inv)) { + ServerUtils.verbose("Entity inventory failed check."); + return false; + } + if (entity instanceof Villager villager) { + for (MerchantRecipe recipe : villager.getRecipes()) { + if (!new ItemCheck().passes(recipe.getResult())) { + ServerUtils.verbose("Villager recipe failed check."); + return false; + } + } + } + if (entity instanceof Mob mob) { + if (!new EquipmentCheck().passes(mob)) { + ServerUtils.verbose("Mob equipment failed check."); + return false; + } + } + if (!entity.getPassengers().isEmpty()) { + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowRecursion) { + ServerUtils.verbose("Entity recursion not allowed."); + return false; + } + for (Entity passenger : entity.getPassengers()) { + if (!passes(passenger)) { + ServerUtils.verbose("Entity passenger failed check."); + return false; + } + } + } + AtomicBoolean failsTiming = new AtomicBoolean(false); + NBT.get(entity, nbt -> { + if (nbt.hasTag("DeathTime") && nbt.getInteger("DeathTime") < 1) { + ServerUtils.verbose("Entity death time check failed."); + failsTiming.set(true); + } + if (nbt.hasTag("Hurttime") && nbt.getInteger("Hurttime") < 1) { + ServerUtils.verbose("Entity hurt time check failed."); + failsTiming.set(true); + } + }); + if (failsTiming.get()) { + ServerUtils.verbose("Entity timing check failed."); + return false; + } + return true; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntitySnapshotCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntitySnapshotCheck.java new file mode 100644 index 0000000..b9e1ce6 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EntitySnapshotCheck.java @@ -0,0 +1,20 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntitySnapshot; + +public class EntitySnapshotCheck extends AbstractCheck { + + @Override + public boolean passes(EntitySnapshot input) { + Location loc = new Location(Bukkit.getWorlds().getFirst(), 0, 1000000, 0); + Entity temp = input.createEntity(loc); + boolean result = new EntityCheck().passes(temp); + ServerUtils.verbose("Temp Entity %s Entity Check", result ? "failed" : "passed"); + temp.remove(); + return result; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EquipmentCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EquipmentCheck.java new file mode 100644 index 0000000..af83534 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/EquipmentCheck.java @@ -0,0 +1,21 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.entity.Mob; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.EquipmentSlot; + +public class EquipmentCheck extends AbstractCheck { + + @Override + public boolean passes(Mob mob) { + ServerUtils.verbose("Running mob check."); + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack item = mob.getEquipment().getItem(slot); + if (item != null && !new ItemCheck().passes(item)) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/InventoryCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/InventoryCheck.java new file mode 100644 index 0000000..0d442f2 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/InventoryCheck.java @@ -0,0 +1,32 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.functions.itemchecks.AbstractCheck; +import me.trouper.sentinel.server.functions.itemchecks.ItemCheck; +import me.trouper.sentinel.utils.InventoryUtils; +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class InventoryCheck extends AbstractCheck { + + @Override + public boolean passes(Inventory inventory) { + ServerUtils.verbose("Running Inventory Check"); + for (ItemStack item : inventory.getContents()) { + if (item == null || item.getType().isAir()) continue; + if (!new ItemCheck().passes(item)) { + ServerUtils.verbose("Inventory item failed check."); + return false; + } + Inventory subInventory = InventoryUtils.getInventory(item); + if (subInventory != null && !Sentinel.getInstance().getDirector().io.nbtConfig.allowRecursion) return false; + if (subInventory != null && !passes(subInventory)) { + ServerUtils.verbose("Sub-inventory failed check."); + return false; + } + } + ServerUtils.verbose("Inventory passed all checks."); + return true; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/ItemCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/ItemCheck.java new file mode 100644 index 0000000..3860338 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/ItemCheck.java @@ -0,0 +1,193 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import de.tr7zw.changeme.nbtapi.NBT; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.utils.InventoryUtils; +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.Material; +import org.bukkit.block.*; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.BundleMeta; +import org.bukkit.inventory.meta.ItemMeta; + +public class ItemCheck extends AbstractCheck { + @Override + public boolean passes(ItemStack item) { + ServerUtils.verbose("Checking item: " + item.getType().name()); + + // No metadata? Nothing to check. + if (item.getItemMeta() == null) { + ServerUtils.verbose("Item passes because it has no metadata."); + return true; + } + ItemMeta meta = item.getItemMeta(); + + // Check for an inventory inside the item. + Inventory inv = InventoryUtils.getInventory(item); + if (inv != null) { + ServerUtils.verbose("Item contains an inventory: " + inv); + if (!new InventoryCheck().passes(inv)) { + ServerUtils.verbose("Item failed inventory check."); + return false; + } + } + + // NBT-based checks (e.g. custom consumables/tools). + var nbt = NBT.itemStackToNBT(item); + var components = nbt.getCompound("components"); + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowCustomConsumables && components.getCompound("minecraft:consumable") != null) { + ServerUtils.verbose("Item is consumable and not allowed."); + return false; + } + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowCustomTools && components.getCompound("minecraft:tool") != null) { + ServerUtils.verbose("Item is custom tool and not allowed."); + return false; + } + var entityData = components.getCompound("minecraft:entity_data"); + if (entityData != null) { + if (item.getType().name().contains("ITEM_FRAME")) { + var itemData = entityData.getCompound("Item"); + ItemStack heldItem = NBT.itemStackFromNBT(itemData); + if (heldItem != null && !new ItemCheck().passes(heldItem)) { + ServerUtils.verbose("Item frame contents failed check."); + return false; + } + } + if (isSpawnEgg(item)) { + if (entityData.hasTag("DeathTime") && entityData.getInteger("DeathTime") < 1) { + ServerUtils.verbose("Egg death time check failed."); + return false; + } + if (entityData.hasTag("Hurttime") && entityData.getInteger("HurtTime") < 1) { + ServerUtils.verbose("Egg hurt time check failed."); + return false; + } + } + } + + // Bundle check – recursively check the contained items. + if (item.getType().name().contains("_BUNDLE") && meta instanceof BundleMeta bm) { + for (ItemStack bundleItem : bm.getItems()) { + if (!passes(bundleItem)) return false; + } + } + + // Campfire check. + if (item.getType().name().contains("CAMPFIRE") && meta instanceof BlockStateMeta blockStateMeta) { + BlockState bs = blockStateMeta.getBlockState(); + if (bs instanceof Campfire campfire) { + for (int slot = 0; slot < 4; slot++) { + ItemStack campfireItem = campfire.getItem(slot); + if (campfireItem != null && !passes(campfireItem)) { + ServerUtils.verbose("Campfire item failed check."); + return false; + } + } + } + } + + // Lectern and Chiseled Bookshelf check (by validating their inventories). + if (item.getType().equals(Material.LECTERN) && meta instanceof BlockStateMeta blockStateMeta) { + BlockState bs = blockStateMeta.getBlockState(); + if (bs instanceof Lectern lectern) { + if (!new InventoryCheck().passes(lectern.getInventory())) { + ServerUtils.verbose("Lectern inventory failed check."); + return false; + } + } + } + if (item.getType().equals(Material.CHISELED_BOOKSHELF) && meta instanceof BlockStateMeta blockStateMeta) { + BlockState bs = blockStateMeta.getBlockState(); + if (bs instanceof ChiseledBookshelf bookshelf) { + if (!new InventoryCheck().passes(bookshelf.getInventory())) { + ServerUtils.verbose("Chiseled bookshelf inventory failed check."); + return false; + } + } + } + + // Spawner check. + if (item.getType().equals(Material.SPAWNER) && meta instanceof BlockStateMeta blockStateMeta) { + BlockState bs = blockStateMeta.getBlockState(); + if (bs instanceof CreatureSpawner spawner) { + if (spawner.getSpawnedEntity() != null) { + if (spawner.getSpawnedEntity().getEntityType().equals(EntityType.FALLING_BLOCK) || + spawner.getSpawnedEntity().getEntityType().equals(EntityType.COMMAND_BLOCK_MINECART)) { + ServerUtils.verbose("Spawner contains disallowed entity type."); + return false; + } + if (!new EntitySnapshotCheck().passes(spawner.getSpawnedEntity())) { + ServerUtils.verbose("Spawner entity snapshot check failed."); + return false; + } + } + } + } + + // Trial Spawner check. + if (item.getType() == Material.TRIAL_SPAWNER && meta instanceof BlockStateMeta blockStateMeta) { + BlockState bs = blockStateMeta.getBlockState(); + if (bs instanceof TrialSpawner trialSpawner) { + if (!new TrialSpawnerCheck().passes(trialSpawner)) return false; + } + } + + // Spawn egg checks. + if (isSpawnEgg(item)) { + if (!SpawnEggCheck.matches(item)) { + ServerUtils.verbose("Spawn egg match check failed."); + return false; + } + if (!new SpawnEggCheck().passes(item)) { + ServerUtils.verbose("Spawn egg check failed."); + return false; + } + } + + // Name, lore, potion, attribute and enchantment checks. + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowName && meta.hasDisplayName()) { + ServerUtils.verbose("Custom names not allowed."); + return false; + } + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowLore && meta.hasLore()) { + ServerUtils.verbose("Custom lore not allowed."); + return false; + } + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowPotions && + (item.getType().equals(Material.POTION) || + item.getType().equals(Material.SPLASH_POTION) || + item.getType().equals(Material.LINGERING_POTION))) { + ServerUtils.verbose("Potions not allowed."); + return false; + } + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowAttributes && meta.hasAttributeModifiers()) { + ServerUtils.verbose("Attribute modifiers not allowed."); + return false; + } + if (Sentinel.getInstance().getDirector().io.nbtConfig.globalMaxEnchant != 0 && new EnchantmentCheck().hasIllegalEnchants(item)) { + ServerUtils.verbose("Illegal enchantments found."); + return false; + } + // Recursion check for use-remainder items. + if (meta.hasUseRemainder()) { + if (!Sentinel.getInstance().getDirector().io.nbtConfig.allowRecursion) { + ServerUtils.verbose("Recursion not allowed."); + return false; + } + if (meta.getUseRemainder() != null && !passes(meta.getUseRemainder())) { + ServerUtils.verbose("Use remainder item failed check."); + return false; + } + } + + ServerUtils.verbose("Item passed all checks."); + return true; + } + + public static boolean isSpawnEgg(ItemStack item) { + return item.getType().name().toLowerCase().contains("spawn_egg"); + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/SpawnEggCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/SpawnEggCheck.java new file mode 100644 index 0000000..79d0ad5 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/SpawnEggCheck.java @@ -0,0 +1,31 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SpawnEggMeta; + +public class SpawnEggCheck extends AbstractCheck { + + @Override + public boolean passes(ItemStack item) { + ServerUtils.verbose("Running spawn egg checks on item: ",item.getType().name()); + if (item.hasItemMeta() && item.getItemMeta() instanceof SpawnEggMeta sem) { + if (sem.getSpawnedEntity() != null && !new EntitySnapshotCheck().passes(sem.getSpawnedEntity())) { + return false; + } + } + return true; + } + + public static boolean matches(ItemStack item) { + if (item.hasItemMeta() && item.getItemMeta() instanceof SpawnEggMeta sem) { + String eggEntityName = item.getType().name().replace("_SPAWN_EGG", ""); + return sem.getSpawnedEntity() != null && + sem.getSpawnedEntity().getEntityType().name().equals(eggEntityName); + } + return false; + } +} diff --git a/src/main/java/me/trouper/sentinel/server/functions/itemchecks/TrialSpawnerCheck.java b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/TrialSpawnerCheck.java new file mode 100644 index 0000000..4b06e98 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/functions/itemchecks/TrialSpawnerCheck.java @@ -0,0 +1,33 @@ +package me.trouper.sentinel.server.functions.itemchecks; + +import me.trouper.sentinel.utils.ServerUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.TrialSpawner; +import org.bukkit.block.spawner.SpawnerEntry; +import org.bukkit.entity.Entity; +import org.bukkit.spawner.TrialSpawnerConfiguration; + +public class TrialSpawnerCheck extends AbstractCheck { + + @Override + public boolean passes(TrialSpawner spawner) { + ServerUtils.verbose("Running trial spawner check."); + if (spawner.getNormalConfiguration() != null) { + TrialSpawnerConfiguration config = spawner.getNormalConfiguration(); + if (config.getSpawnedEntity() != null && !new EntitySnapshotCheck().passes(config.getSpawnedEntity())) { + ServerUtils.verbose("Trial Spawner failed check: Normal entity snapshot not allowed."); + return false; + } + } + if (spawner.getOminousConfiguration() != null) { + TrialSpawnerConfiguration config = spawner.getOminousConfiguration(); + if (config.getSpawnedEntity() != null && !new EntitySnapshotCheck().passes(config.getSpawnedEntity())) { + ServerUtils.verbose("Trial Spawner failed check: Ominous entity snapshot not allowed."); + return false; + } + } + return true; + } +} + diff --git a/src/main/java/me/trouper/sentinel/server/gui/Items.java b/src/main/java/me/trouper/sentinel/server/gui/Items.java index ad5b265..0b2019e 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/Items.java +++ b/src/main/java/me/trouper/sentinel/server/gui/Items.java @@ -2,7 +2,6 @@ package me.trouper.sentinel.server.gui; import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.startup.Auth; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.Material; @@ -62,7 +61,8 @@ public class Items { .name(Text.color("&bChat Config")) .lore(Text.color("&8&l➥&7 Spam Filter")) .lore(Text.color("&8&l➥&7 Profanity Filter")) - .lore(Text.color("&8&l➥&7 Regex Filters")) + .lore(Text.color("&8&l➥&7 Unicode Filter")) + .lore(Text.color("&8&l➥&7 URL Filter")) .enchant(Enchantment.PROTECTION,64) .flag(ItemFlag.HIDE_ENCHANTS) .build(); @@ -70,16 +70,18 @@ public class Items { public static final ItemStack ANTI_NUKE_CONFIG = ItemBuilder.create() .material(Material.TNT) .name(Text.color("&cAnti-Nuke Config")) - .lore(Text.color("&8&l➥&7 Command Block Whitelist")) - .lore(Text.color("&8&l➥&7 Command Block editing")) - .lore(Text.color("&8&l➥&7 Command Block placing")) - .lore(Text.color("&8&l➥&7 Command Block using")) - .lore(Text.color("&8&l➥&7 Command Block Minecart placing")) - .lore(Text.color("&8&l➥&7 Command Block Minecart using")) - .lore(Text.color("&8&l➥&7 Creative Hotbar Items")) + .lore(Text.color("&8&l➥&7 Manage all violations")) .enchant(Enchantment.PROTECTION,64) .flag(ItemFlag.HIDE_ENCHANTS) .build(); + + public static final ItemStack WHITELIST = ItemBuilder.create() + .material(Material.TNT) + .name(Text.color("&aCommand Block Whitelist")) + .lore(Text.color("&8&l➥&7 Manage running command blocks")) + .enchant(Enchantment.PROTECTION, 64) + .flag(ItemFlag.HIDE_ENCHANTS) + .build(); public static ItemStack configItem(String valueName, Material material, String description) { ServerUtils.verbose("Items#configItem: Creating a config item:\n Value Name -> %s\nMaterial in use -> %s".formatted(valueName,material.toString())); diff --git a/src/main/java/me/trouper/sentinel/server/gui/MainGUI.java b/src/main/java/me/trouper/sentinel/server/gui/MainGUI.java index 1bafef7..5d7bd5c 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/MainGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/MainGUI.java @@ -2,6 +2,8 @@ package me.trouper.sentinel.server.gui; import io.github.itzispyder.pdk.plugin.gui.CustomGui; import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.server.gui.config.ConfigGUI; +import me.trouper.sentinel.server.gui.whitelist.WhitelistGUI; import me.trouper.sentinel.utils.PlayerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.entity.Player; @@ -21,10 +23,15 @@ public class MainGUI { .size(27) .onDefine(this::blankPage) .defineMain(this::mainClick) - .define(12,Items.CREDITS) - .define(14,Items.CONFIG,this::openConfig) + .define(11,Items.CREDITS) + .define(13,Items.WHITELIST,this::openWhitelist) + .define(15,Items.CONFIG,this::openConfig) .build(); + private void openWhitelist(InventoryClickEvent e) { + e.getWhoClicked().openInventory(new WhitelistGUI().createGUI((Player) e.getWhoClicked()).getInventory()); + } + private void openConfig(InventoryClickEvent e) { e.getWhoClicked().openInventory(new ConfigGUI().home.getInventory()); } @@ -42,7 +49,7 @@ public class MainGUI { public static boolean verify(Player p) { if (PlayerUtils.isTrusted(p)) return true; - Sentinel.log.info("WARNING: %s has just attempted to use the GUI without authorization. This has been prevented by Sentinel, as we are NOT Vulcan AntiCheat."); + Sentinel.getInstance().getLogger().info("WARNING: %s has just attempted to use the GUI without authorization. This has been prevented by Sentinel, as we are NOT Vulcan AntiCheat."); p.closeInventory(); return false; } diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/AntiNukeGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/AntiNukeGUI.java index 9182050..9190dd3 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/AntiNukeGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/AntiNukeGUI.java @@ -2,11 +2,27 @@ package me.trouper.sentinel.server.gui.config; import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import me.trouper.sentinel.server.gui.ConfigGUI; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockEdit; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.command.CommandBlockUse; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockUse; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockUse; +import me.trouper.sentinel.server.events.violations.command.DangerousCommand; +import me.trouper.sentinel.server.events.violations.command.LoggedCommand; +import me.trouper.sentinel.server.events.violations.command.SpecificCommand; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartBreak; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartPlace; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartUse; +import me.trouper.sentinel.server.events.violations.players.CreativeHotbar; +import me.trouper.sentinel.server.events.violations.whitelist.CommandBlockExecute; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.nuke.CommandGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.*; +import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -17,36 +33,48 @@ import org.bukkit.inventory.ItemStack; public class AntiNukeGUI { public final CustomGui home = CustomGui.create() .title(Text.color("&6&lSentinel &8»&0 Choose a check")) - .size(54) + .size(9*5) .onDefine(this::blankPage) .defineMain(this::mainClick) - .define(53, Items.BACK, e->{ + .define((9*5)-1, Items.BACK, e->{ e.getWhoClicked().openInventory(new ConfigGUI().home.getInventory()); }) - .define(10,COMMAND_BLOCK_WHITELIST, e->{ - e.getWhoClicked().openInventory(new CBExecuteGUI().home.getInventory()); - }) - .define(12,COMMAND_BLOCK_PLACE, e->{ - e.getWhoClicked().openInventory(new CBPlaceGUI().home.getInventory()); - }) - .define(14,COMMAND_BLOCK_USE, e->{ - e.getWhoClicked().openInventory(new CBUseGUI().home.getInventory()); - }) - .define(16,COMMAND_BLOCK_EDITING, e->{ - e.getWhoClicked().openInventory(new CBEditGUI().home.getInventory()); - }) - .define(37,COMMAND_BLOCK_MINECART_USE, e->{ - e.getWhoClicked().openInventory(new CBMCUseGUI().home.getInventory()); - }) - .define(39,COMMAND_BLOCK_MINECART_PLACE, e->{ - e.getWhoClicked().openInventory(new CBMCPlaceGUI().home.getInventory()); - }) - .define(41,COMMAND_EXECUTE, e->{ - e.getWhoClicked().openInventory(new CommandGUI().home.getInventory()); - }) - .define(43,HOTBAR_ACTION, e->{ - e.getWhoClicked().openInventory(new HotbarActionGUI().home.getInventory()); - }) + .define(10,getCheckItem(Material.COMMAND_BLOCK,"Command Block Break"), + e->e.getWhoClicked().openInventory(new CommandBlockBreak().getConfigGui().getInventory())) + .define(11,getCheckItem(Material.REPEATING_COMMAND_BLOCK,"Command Block Edit"), + e->e.getWhoClicked().openInventory(new CommandBlockEdit().getConfigGui().getInventory())) + .define(12,getCheckItem(Material.CHAIN_COMMAND_BLOCK,"Command Block Place"), + e->e.getWhoClicked().openInventory(new CommandBlockPlace().getConfigGui().getInventory())) + .define(13,getCheckItem(Material.CHAIN_COMMAND_BLOCK,"Command Block Use"), + e->e.getWhoClicked().openInventory(new CommandBlockUse().getConfigGui().getInventory())) + .define(14,getCheckItem(Material.JIGSAW,"Jigsaw Block Break"), + e->e.getWhoClicked().openInventory(new JigsawBlockBreak().getConfigGui().getInventory())) + .define(15,getCheckItem(Material.JIGSAW,"Jigsaw Block Place"), + e->e.getWhoClicked().openInventory(new JigsawBlockPlace().getConfigGui().getInventory())) + .define(16,getCheckItem(Material.JIGSAW,"Jigsaw Block Use"), + e->e.getWhoClicked().openInventory(new JigsawBlockUse().getConfigGui().getInventory())) + .define(19,getCheckItem(Material.STRUCTURE_BLOCK,"Structure Block Break"), + e->e.getWhoClicked().openInventory(new StructureBlockBreak().getConfigGui().getInventory())) + .define(20,getCheckItem(Material.STRUCTURE_BLOCK,"Structure Block Place"), + e->e.getWhoClicked().openInventory(new StructureBlockPlace().getConfigGui().getInventory())) + .define(21,getCheckItem(Material.STRUCTURE_BLOCK,"Structure Block Use"), + e->e.getWhoClicked().openInventory(new StructureBlockUse().getConfigGui().getInventory())) + .define(22,getCheckItem(Material.TNT,"Dangerous Commands"), + e->e.getWhoClicked().openInventory(new DangerousCommand().getConfigGui().getInventory())) + .define(23,getCheckItem(Material.ENDER_PEARL,"Specific Commands"), + e->e.getWhoClicked().openInventory(new SpecificCommand().getConfigGui().getInventory())) + .define(24,getCheckItem(Material.SPYGLASS,"Logged Commands"), + e->e.getWhoClicked().openInventory(new LoggedCommand().getConfigGui().getInventory())) + .define(25,getCheckItem(Material.TNT_MINECART,"Command Minecart Break"), + e->e.getWhoClicked().openInventory(new CommandMinecartBreak().getConfigGui().getInventory())) + .define(29,getCheckItem(Material.COMMAND_BLOCK_MINECART,"Command Minecart Place"), + e->e.getWhoClicked().openInventory(new CommandMinecartPlace().getConfigGui().getInventory())) + .define(30,getCheckItem(Material.COMMAND_BLOCK_MINECART,"Command Minecart Use"), + e->e.getWhoClicked().openInventory(new CommandMinecartUse().getConfigGui().getInventory())) + .define(32,getCheckItem(Material.DIAMOND_SWORD,"NBT Item Pull"), + e->e.getWhoClicked().openInventory(new CreativeHotbar().getConfigGui().getInventory())) + .define(33,getCheckItem(Material.EMERALD,"Command Block Whitelist"), + e->e.getWhoClicked().openInventory(new CommandBlockExecute().getConfigGui().getInventory())) .build(); private void mainClick(InventoryClickEvent e) { @@ -55,59 +83,17 @@ public class AntiNukeGUI { } private void blankPage(Inventory inv) { + ServerUtils.verbose("Making anti-nuke page"); for (int i = 0; i < inv.getSize(); i++) { inv.setItem(i,Items.BLANK); } } - private static final ItemStack COMMAND_BLOCK_EDITING = ItemBuilder.create() - .material(Material.DEBUG_STICK) - .name(Text.color("&bCommand Block Editing")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_BLOCK_WHITELIST = ItemBuilder.create() - .material(Material.EMERALD) - .name(Text.color("&bCommand Block Whitelist")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_BLOCK_MINECART_PLACE = ItemBuilder.create() - .material(Material.RAIL) - .name(Text.color("&bCommand Block Minecart Placing")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_BLOCK_MINECART_USE = ItemBuilder.create() - .material(Material.COMMAND_BLOCK_MINECART) - .name(Text.color("&bCommand Block Minecart Using")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_BLOCK_PLACE = ItemBuilder.create() - .material(Material.CHAIN_COMMAND_BLOCK) - .name(Text.color("&bCommand Block Placing")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_BLOCK_USE = ItemBuilder.create() - .material(Material.REPEATING_COMMAND_BLOCK) - .name(Text.color("&bCommand Block Using")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack COMMAND_EXECUTE = ItemBuilder.create() - .material(Material.SPYGLASS) - .name(Text.color("&bCommand Execution")) - .lore(Text.color("&8&l➥&7 Dangerous Commands")) - .lore(Text.color("&8&l➥&7 Logged Commands")) - .lore(Text.color("&8&l➥&7 Specific Commands")) - .build(); - - private static final ItemStack HOTBAR_ACTION = ItemBuilder.create() - .material(Material.DIAMOND_SWORD) - .name(Text.color("&bNBT Items")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - + private static ItemStack getCheckItem(Material item, String name) { + return ItemBuilder.create() + .material(item) + .name(Text.color("&b" + name)) + .lore(Text.color("&8&l➥&7 Modify this check")) + .build(); + } } diff --git a/src/main/java/me/trouper/sentinel/server/gui/ConfigGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/ConfigGUI.java similarity index 82% rename from src/main/java/me/trouper/sentinel/server/gui/ConfigGUI.java rename to src/main/java/me/trouper/sentinel/server/gui/config/ConfigGUI.java index e2ea3ba..476ff43 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/ConfigGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/ConfigGUI.java @@ -1,8 +1,9 @@ -package me.trouper.sentinel.server.gui; +package me.trouper.sentinel.server.gui.config; import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.server.gui.config.ChatGUI; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.server.gui.MainGUI; +import me.trouper.sentinel.server.gui.config.chat.ChatGUI; import me.trouper.sentinel.utils.Text; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; @@ -14,7 +15,7 @@ public class ConfigGUI { .size(27) .onDefine(this::blankPage) .defineMain(this::mainClick) - .define(12, Items.ANTI_NUKE_CONFIG,e->{ + .define(12, Items.ANTI_NUKE_CONFIG, e->{ e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); }) .define(14,Items.CHAT_CONFIG,e->{ diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/ChatGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/chat/ChatGUI.java similarity index 88% rename from src/main/java/me/trouper/sentinel/server/gui/config/ChatGUI.java rename to src/main/java/me/trouper/sentinel/server/gui/config/chat/ChatGUI.java index e745281..36dee5a 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/ChatGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/chat/ChatGUI.java @@ -1,14 +1,10 @@ -package me.trouper.sentinel.server.gui.config; +package me.trouper.sentinel.server.gui.config.chat; import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import me.trouper.sentinel.server.gui.ConfigGUI; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.chat.ProfanityFilterGUI; -import me.trouper.sentinel.server.gui.config.chat.SpamFilterGUI; -import me.trouper.sentinel.server.gui.config.chat.UnicodeFilterGUI; -import me.trouper.sentinel.server.gui.config.chat.UrlFilterGUI; +import me.trouper.sentinel.server.gui.config.ConfigGUI; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import org.bukkit.Material; diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.java index e82f10f..d3c8e8a 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/chat/ProfanityFilterGUI.java @@ -8,7 +8,6 @@ import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.ChatGUI; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import net.kyori.adventure.text.Component; @@ -17,7 +16,6 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -44,7 +42,7 @@ public class ProfanityFilterGUI { } ServerUtils.verbose("ProfanityFilterGUI#blankPage Page now blank"); ItemStack top = Items.RED; - if (Sentinel.mainConfig.chat.profanityFilter.enabled) { + if (Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.enabled) { top = Items.GREEN; } @@ -54,18 +52,18 @@ public class ProfanityFilterGUI { ServerUtils.verbose("ProfanityFilterGUI#blankPage Adding GUI Items"); inv.setItem(53,Items.BACK); - inv.setItem(3,Items.booleanItem(Sentinel.mainConfig.chat.profanityFilter.enabled, Items.configItem("Profanity Filter Toggle",Material.CLOCK,"Enable or Disable the whole Profanity filter"))); - inv.setItem(5,Items.booleanItem(Sentinel.mainConfig.chat.profanityFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); - inv.setItem(10,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.lowScore, Items.configItem("Low Score Gain", Material.WHITE_WOOL, "How much score will be added if the player \ndid not attempt to bypass the filter."))); - inv.setItem(19,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.mediumLowScore, Items.configItem("Medium-Low Score Gain", Material.LIME_WOOL, "How much score will be added if the player \nused l33t speak to attempt a bypass"))); - inv.setItem(28,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.mediumScore, Items.configItem("Medium Score Gain", Material.YELLOW_WOOL, "How much score will be added if the player \nused sp/ecia|l characters to attempt a bypass"))); - inv.setItem(37,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.mediumHighScore, Items.configItem("Medium-High Score Gain", Material.ORANGE_WOOL, "How much score will be added if the player \nused reeeeeeepeating letters to attempt a bypass"))); - inv.setItem(46,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.highScore, Items.configItem("High Score Gain", Material.RED_WOOL, "How much score will be added if the player \nused pun. ctua, tion or spaces to attempt a bypass"))); - inv.setItem(29,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.regexScore, Items.configItem("Regex Score Gain", Material.DISPENSER, "How much score will be added if the player \nmatched the regex setting throughout \nthe processing of the message"))); - inv.setItem(22,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.punishScore, Items.configItem("Punish Score", Material.IRON_BARS, "If the player's score is above this \nthe punishment commands will be ran."))); - inv.setItem(33,Items.intItem(Sentinel.mainConfig.chat.profanityFilter.scoreDecay, Items.configItem("Score Decay", Material.DEAD_BUBBLE_CORAL_BLOCK, "How much score players will loose each minute."))); - inv.setItem(31,Items.stringListItem(Sentinel.mainConfig.chat.profanityFilter.profanityPunishCommands,Material.WOODEN_AXE, "Default Punishment Commands", "%player% will be replaced with the offender's name")); - inv.setItem(40,Items.stringListItem(Sentinel.mainConfig.chat.profanityFilter.strictPunishCommands,Material.DIAMOND_AXE, "Strict Punishment Commands", "If words from the strict words list are flagged, \nthis list will be ran instead \n%player% will be replaced with the offender's name")); + inv.setItem(3,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.enabled, Items.configItem("Profanity Filter Toggle",Material.CLOCK,"Enable or Disable the whole Profanity filter"))); + inv.setItem(5,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); + inv.setItem(10,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.lowScore, Items.configItem("Low Score Gain", Material.WHITE_WOOL, "How much score will be added if the player \ndid not attempt to bypass the filter."))); + inv.setItem(19,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumLowScore, Items.configItem("Medium-Low Score Gain", Material.LIME_WOOL, "How much score will be added if the player \nused l33t speak to attempt a bypass"))); + inv.setItem(28,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumScore, Items.configItem("Medium Score Gain", Material.YELLOW_WOOL, "How much score will be added if the player \nused sp/ecia|l characters to attempt a bypass"))); + inv.setItem(37,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumHighScore, Items.configItem("Medium-High Score Gain", Material.ORANGE_WOOL, "How much score will be added if the player \nused reeeeeeepeating letters to attempt a bypass"))); + inv.setItem(46,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.highScore, Items.configItem("High Score Gain", Material.RED_WOOL, "How much score will be added if the player \nused pun. ctua, tion or spaces to attempt a bypass"))); + inv.setItem(29,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.regexScore, Items.configItem("Regex Score Gain", Material.DISPENSER, "How much score will be added if the player \nmatched the regex setting throughout \nthe processing of the message"))); + inv.setItem(22,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.punishScore, Items.configItem("Punish Score", Material.IRON_BARS, "If the player's score is above this \nthe punishment commands will be ran."))); + inv.setItem(33,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.scoreDecay, Items.configItem("Score Decay", Material.DEAD_BUBBLE_CORAL_BLOCK, "How much score players will loose each minute."))); + inv.setItem(31,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.profanityPunishCommands,Material.WOODEN_AXE, "Default Punishment Commands", "%player% will be replaced with the offender's name")); + inv.setItem(40,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.strictPunishCommands,Material.DIAMOND_AXE, "Strict Punishment Commands", "If words from the strict words list are flagged, \nthis list will be ran instead \n%player% will be replaced with the offender's name")); } catch (Exception e) { e.printStackTrace(); } @@ -76,35 +74,35 @@ public class ProfanityFilterGUI { if (!MainGUI.verify((Player) e.getWhoClicked())) return; switch (e.getSlot()) { case 3 -> { - Sentinel.mainConfig.chat.profanityFilter.enabled = !Sentinel.mainConfig.chat.profanityFilter.enabled; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.enabled = !Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.enabled; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 5 -> { - Sentinel.mainConfig.chat.profanityFilter.silent = !Sentinel.mainConfig.chat.profanityFilter.silent; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.silent = !Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.silent; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } - case 10 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.lowScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.lowScore); - case 19 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumLowScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.mediumLowScore); - case 28 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.mediumScore); - case 37 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumHighScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.mediumHighScore); - case 46 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.highScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.highScore); - case 29 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.regexScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.regexScore); - case 22 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.punishScore = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.punishScore); - case 33 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.scoreDecay = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.profanityFilter.scoreDecay); + case 10 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.lowScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.lowScore); + case 19 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumLowScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumLowScore); + case 28 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumScore); + case 37 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.mediumHighScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.mediumHighScore); + case 46 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.highScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.highScore); + case 29 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.regexScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.regexScore); + case 22 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.punishScore = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.punishScore); + case 33 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.profanityFilter.scoreDecay = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.scoreDecay); case 31 -> { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.profanityFilter.profanityPunishCommands.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.profanityFilter.profanityPunishCommands); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.profanityPunishCommands); return; } - Sentinel.mainConfig.chat.profanityFilter.profanityPunishCommands.clear(); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.profanityPunishCommands.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } @@ -112,17 +110,17 @@ public class ProfanityFilterGUI { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.profanityFilter.strictPunishCommands.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.profanityFilter.strictPunishCommands); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.strictPunishCommands); return; } - Sentinel.mainConfig.chat.profanityFilter.strictPunishCommands.clear(); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.profanityFilter.strictPunishCommands.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } } } - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.mainConfig); + public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.mainConfig); private void queuePlayer(Player player, BiConsumer action, String currentValue) { MainGUI.awaitingCallback.add(player.getUniqueId()); diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.java index bcccd27..30ef5f4 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/chat/SpamFilterGUI.java @@ -8,8 +8,6 @@ import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.ChatGUI; -import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; @@ -17,7 +15,6 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -43,7 +40,7 @@ public class SpamFilterGUI { } ItemStack top = Items.RED; - if (Sentinel.mainConfig.chat.spamFilter.enabled) { + if (Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.enabled) { top = Items.GREEN; } @@ -52,18 +49,18 @@ public class SpamFilterGUI { } inv.setItem(53,Items.BACK); - inv.setItem(3,Items.booleanItem(Sentinel.mainConfig.chat.spamFilter.enabled, Items.configItem("Spam Filter Toggle", Material.CLOCK, "Enable or disable the whole Spam Filter"))); - inv.setItem(5,Items.booleanItem(Sentinel.mainConfig.chat.spamFilter.silent, Items.configItem("Silent Toggle", Material.FEATHER, "Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); - inv.setItem(10,Items.intItem(Sentinel.mainConfig.chat.spamFilter.defaultGain, Items.configItem("Default Heat Gain", Material.BUCKET, "How much heat will be added to each message."))); - inv.setItem(19,Items.intItem(Sentinel.mainConfig.chat.spamFilter.lowGain, Items.configItem("Low Heat Gain", Material.WATER_BUCKET, "Extra heat to be added if the \nmessage is greater than 25% similar \nto their previous message."))); - inv.setItem(28,Items.intItem(Sentinel.mainConfig.chat.spamFilter.mediumGain, Items.configItem("Medium Heat Gain", Material.COD_BUCKET, "Extra heat to be added if the \nmessage is greater than 50% similar \nto their previous message."))); - inv.setItem(37,Items.intItem(Sentinel.mainConfig.chat.spamFilter.highGain, Items.configItem("High Heat Gain", Material.PUFFERFISH_BUCKET, "Extra heat to be added if the \nmessage is greater than 90% similar \nto their previous message."))); - inv.setItem(46,Items.intItem(Sentinel.mainConfig.chat.spamFilter.blockHeat, Items.configItem("Block Heat", Material.BARRIER, "If the player's heat is above this \nthen their message will be blocked and \nflagged as spam."))); - inv.setItem(21,Items.intItem(Sentinel.mainConfig.chat.spamFilter.blockSimilarity, Items.configItem("Block Similarity", Material.BARRIER, "If the message's similarity is above \nthis, it will get automatically blocked \nand flagged as spam."))); - inv.setItem(23,Items.intItem(Sentinel.mainConfig.chat.spamFilter.punishHeat, Items.configItem("Punish Heat", Material.IRON_BARS, "If the player's heat is above this \nthe punishment commands will be ran."))); - inv.setItem(25,Items.intItem(Sentinel.mainConfig.chat.spamFilter.heatDecay, Items.configItem("Heat Decay", Material.DEAD_BUBBLE_CORAL_BLOCK, "How much heat players will loose each second."))); - inv.setItem(32,Items.stringListItem(Sentinel.mainConfig.chat.spamFilter.punishCommands,Material.DIAMOND_AXE, "Punishment Commands", "%player% will be replaced with the offender's name")); - inv.setItem(34,Items.stringListItem(Sentinel.mainConfig.chat.spamFilter.whitelist,Material.PAPER, "Message Whitelist", "Messages which will be ignored by the spam filter")); + inv.setItem(3,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.enabled, Items.configItem("Spam Filter Toggle", Material.CLOCK, "Enable or disable the whole Spam Filter"))); + inv.setItem(5,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.silent, Items.configItem("Silent Toggle", Material.FEATHER, "Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); + inv.setItem(10,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.defaultGain, Items.configItem("Default Heat Gain", Material.BUCKET, "How much heat will be added to each message."))); + inv.setItem(19,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.lowGain, Items.configItem("Low Heat Gain", Material.WATER_BUCKET, "Extra heat to be added if the \nmessage is greater than 25% similar \nto their previous message."))); + inv.setItem(28,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.mediumGain, Items.configItem("Medium Heat Gain", Material.COD_BUCKET, "Extra heat to be added if the \nmessage is greater than 50% similar \nto their previous message."))); + inv.setItem(37,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.highGain, Items.configItem("High Heat Gain", Material.PUFFERFISH_BUCKET, "Extra heat to be added if the \nmessage is greater than 90% similar \nto their previous message."))); + inv.setItem(46,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockHeat, Items.configItem("Block Heat", Material.BARRIER, "If the player's heat is above this \nthen their message will be blocked and \nflagged as spam."))); + inv.setItem(21,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity, Items.configItem("Block Similarity", Material.BARRIER, "If the message's similarity is above \nthis, it will get automatically blocked \nand flagged as spam."))); + inv.setItem(23,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishHeat, Items.configItem("Punish Heat", Material.IRON_BARS, "If the player's heat is above this \nthe punishment commands will be ran."))); + inv.setItem(25,Items.intItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.heatDecay, Items.configItem("Heat Decay", Material.DEAD_BUBBLE_CORAL_BLOCK, "How much heat players will loose each second."))); + inv.setItem(32,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishCommands,Material.DIAMOND_AXE, "Punishment Commands", "%player% will be replaced with the offender's name")); + inv.setItem(34,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.whitelist,Material.PAPER, "Message Whitelist", "Messages which will be ignored by the spam filter")); } private void mainClick(InventoryClickEvent e) { @@ -73,40 +70,40 @@ public class SpamFilterGUI { switch (e.getSlot()) { case 3 -> { - Sentinel.mainConfig.chat.spamFilter.enabled = !Sentinel.mainConfig.chat.spamFilter.enabled; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.enabled = !Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.enabled; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 5 -> { - Sentinel.mainConfig.chat.spamFilter.silent = !Sentinel.mainConfig.chat.spamFilter.silent; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.silent = !Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.silent; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } - case 10 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.defaultGain = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.defaultGain); - case 19 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.lowGain = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.lowGain); - case 28 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.mediumGain = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.mediumGain); - case 37 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.highGain = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.highGain); - case 46 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.blockHeat = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.blockHeat); - case 21 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.blockSimilarity = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.blockSimilarity); - case 23 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.punishHeat = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.punishHeat); - case 25 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.heatDecay = args.getAll().toInt(),"" + Sentinel.mainConfig.chat.spamFilter.heatDecay); + case 10 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.defaultGain = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.defaultGain); + case 19 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.lowGain = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.lowGain); + case 28 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.mediumGain = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.mediumGain); + case 37 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.highGain = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.highGain); + case 46 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.blockHeat = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockHeat); + case 21 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.blockSimilarity = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.blockSimilarity); + case 23 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.punishHeat = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishHeat); + case 25 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.spamFilter.heatDecay = args.getAll().toInt(),"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.heatDecay); case 32 -> { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.spamFilter.punishCommands.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.spamFilter.punishCommands); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishCommands); return; } - Sentinel.mainConfig.chat.spamFilter.punishCommands.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.spamFilter.punishCommands.clear(); blankPage(e.getInventory()); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); } } } - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.mainConfig); + public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.mainConfig); private void queuePlayer(Player player, BiConsumer action, String currentValue) { MainGUI.awaitingCallback.add(player.getUniqueId()); diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/chat/UnicodeFilterGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/chat/UnicodeFilterGUI.java index 75c56b1..601d0b9 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/chat/UnicodeFilterGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/chat/UnicodeFilterGUI.java @@ -8,7 +8,6 @@ import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.ChatGUI; import me.trouper.sentinel.utils.ServerUtils; import me.trouper.sentinel.utils.Text; import net.kyori.adventure.text.Component; @@ -41,7 +40,7 @@ public class UnicodeFilterGUI { } ServerUtils.verbose("Unicode Filter GUI blank!"); ItemStack top = Items.RED; - if (Sentinel.mainConfig.chat.unicodeFilter.enabled) { + if (Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.enabled) { top = Items.GREEN; } @@ -49,11 +48,11 @@ public class UnicodeFilterGUI { inv.setItem(i,top); } - inv.setItem(3,Items.booleanItem(Sentinel.mainConfig.chat.unicodeFilter.enabled, Items.configItem("Unicode Filter Toggle", Material.CLOCK,"Enable or Disable the whole Unicode filter"))); - inv.setItem(5,Items.booleanItem(Sentinel.mainConfig.chat.unicodeFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); - inv.setItem(20,Items.booleanItem(Sentinel.mainConfig.chat.unicodeFilter.punished,Items.configItem("Punished",Material.IRON_BARS,"Toggles execution of punishment commands."))); - inv.setItem(22,Items.stringItem(Sentinel.mainConfig.chat.unicodeFilter.regex,Items.configItem("Allowed Char Regex",Material.DISPENSER,"Toggles execution of punishment commands."))); - inv.setItem(24,Items.stringListItem(Sentinel.mainConfig.chat.unicodeFilter.punishCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands which will be executed if punishment is enabled.")); + inv.setItem(3,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.enabled, Items.configItem("Unicode Filter Toggle", Material.CLOCK,"Enable or Disable the whole Unicode filter"))); + inv.setItem(5,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); + inv.setItem(20,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punished,Items.configItem("Punished",Material.IRON_BARS,"Toggles execution of punishment commands."))); + inv.setItem(22,Items.stringItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.regex,Items.configItem("Allowed Char Regex",Material.DISPENSER,"Toggles execution of punishment commands."))); + inv.setItem(24,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punishCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands which will be executed if punishment is enabled.")); } @@ -63,41 +62,41 @@ public class UnicodeFilterGUI { switch (e.getSlot()) { case 3 -> { - Sentinel.mainConfig.chat.unicodeFilter.enabled = !Sentinel.mainConfig.chat.unicodeFilter.enabled; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.enabled = !Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.enabled; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 5 -> { - Sentinel.mainConfig.chat.unicodeFilter.silent = !Sentinel.mainConfig.chat.unicodeFilter.silent; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.silent = !Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.silent; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 20 -> { - Sentinel.mainConfig.chat.unicodeFilter.punished = !Sentinel.mainConfig.chat.unicodeFilter.punished; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punished = !Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punished; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } - case 22 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.unicodeFilter.regex = args.getAll().toString(),Sentinel.mainConfig.chat.unicodeFilter.regex); + case 22 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.unicodeFilter.regex = args.getAll().toString(),Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.regex); case 24 -> { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.unicodeFilter.punishCommands.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.unicodeFilter.punishCommands); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punishCommands); return; } - Sentinel.mainConfig.chat.unicodeFilter.punishCommands.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.unicodeFilter.punishCommands.clear(); blankPage(e.getInventory()); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); } } } - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.mainConfig); + public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.mainConfig); private void queuePlayer(Player player, BiConsumer action, String currentValue) { MainGUI.awaitingCallback.add(player.getUniqueId()); diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/chat/UrlFilterGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/chat/UrlFilterGUI.java index aa8989e..ec00b9b 100644 --- a/src/main/java/me/trouper/sentinel/server/gui/config/chat/UrlFilterGUI.java +++ b/src/main/java/me/trouper/sentinel/server/gui/config/chat/UrlFilterGUI.java @@ -9,7 +9,6 @@ import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; import me.trouper.sentinel.server.gui.Items; import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.ChatGUI; import me.trouper.sentinel.utils.Text; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; @@ -40,7 +39,7 @@ public class UrlFilterGUI implements CustomListener { } ItemStack top = Items.RED; - if (Sentinel.mainConfig.chat.urlFilter.enabled) { + if (Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.enabled) { top = Items.GREEN; } @@ -48,12 +47,12 @@ public class UrlFilterGUI implements CustomListener { inv.setItem(i,top); } - inv.setItem(3,Items.booleanItem(Sentinel.mainConfig.chat.urlFilter.enabled, Items.configItem("Unicode Filter Toggle", Material.CLOCK,"Enable or Disable the whole Unicode filter"))); - inv.setItem(5,Items.booleanItem(Sentinel.mainConfig.chat.urlFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); - inv.setItem(19,Items.booleanItem(Sentinel.mainConfig.chat.urlFilter.punished,Items.configItem("Punished",Material.IRON_BARS,"Toggles execution of punishment commands."))); - inv.setItem(21,Items.stringItem(Sentinel.mainConfig.chat.urlFilter.regex,Items.configItem("Allowed Char Regex",Material.DISPENSER,"Toggles execution of punishment commands."))); - inv.setItem(23,Items.stringListItem(Sentinel.mainConfig.chat.urlFilter.punishCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands which will be executed if punishment is enabled.")); - inv.setItem(25,Items.stringListItem(Sentinel.mainConfig.chat.urlFilter.whitelist,Material.PAPER,"Whitelist","URLs which will not flag the filter.")); + inv.setItem(3,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.enabled, Items.configItem("Unicode Filter Toggle", Material.CLOCK,"Enable or Disable the whole Unicode filter"))); + inv.setItem(5,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.silent, Items.configItem("Silent Mode",Material.FEATHER,"Whether to notify players that their messages \nwere blocked. Enabling could help deter bypassing."))); + inv.setItem(19,Items.booleanItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punished,Items.configItem("Punished",Material.IRON_BARS,"Toggles execution of punishment commands."))); + inv.setItem(21,Items.stringItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.regex,Items.configItem("Allowed Char Regex",Material.DISPENSER,"Toggles execution of punishment commands."))); + inv.setItem(23,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punishCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands which will be executed if punishment is enabled.")); + inv.setItem(25,Items.stringListItem(Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.whitelist,Material.PAPER,"Whitelist","URLs which will not flag the filter.")); } @@ -63,53 +62,53 @@ public class UrlFilterGUI implements CustomListener { switch (e.getSlot()) { case 3 -> { - Sentinel.mainConfig.chat.urlFilter.enabled = !Sentinel.mainConfig.chat.urlFilter.enabled; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.enabled = !Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.enabled; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 5 -> { - Sentinel.mainConfig.chat.urlFilter.silent = !Sentinel.mainConfig.chat.urlFilter.silent; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.silent = !Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.silent; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } case 19 -> { - Sentinel.mainConfig.chat.urlFilter.punished = !Sentinel.mainConfig.chat.urlFilter.punished; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punished = !Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punished; + Sentinel.getInstance().getDirector().io.mainConfig.save(); blankPage(e.getInventory()); } - case 21 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.urlFilter.regex = args.getAll().toString(),Sentinel.mainConfig.chat.urlFilter.regex); + case 21 -> queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> cfg.chat.urlFilter.regex = args.getAll().toString(),Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.regex); case 23 -> { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.urlFilter.punishCommands.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.urlFilter.punishCommands); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punishCommands); return; } - Sentinel.mainConfig.chat.urlFilter.punishCommands.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.punishCommands.clear(); blankPage(e.getInventory()); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); } case 25 -> { if (e.isLeftClick()) { queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { cfg.chat.urlFilter.whitelist.add(args.getAll().toString()); - },"" + Sentinel.mainConfig.chat.urlFilter.whitelist); + },"" + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.whitelist); return; } - Sentinel.mainConfig.chat.urlFilter.whitelist.clear(); + Sentinel.getInstance().getDirector().io.mainConfig.chat.urlFilter.whitelist.clear(); blankPage(e.getInventory()); - Sentinel.mainConfig.save(); + Sentinel.getInstance().getDirector().io.mainConfig.save(); } } } - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.mainConfig); + public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.mainConfig); private void queuePlayer(Player player, BiConsumer action, String currentValue) { MainGUI.awaitingCallback.add(player.getUniqueId()); diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.java deleted file mode 100644 index 20a51f6..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/CommandGUI.java +++ /dev/null @@ -1,67 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke; - -import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.DangerousCMDGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.LoggedCMDGUI; -import me.trouper.sentinel.server.gui.config.nuke.checks.command.SpecificCMDGUI; -import me.trouper.sentinel.utils.Text; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -public class CommandGUI { - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 Choose a check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .define(11,SPECIFIC, e->{ - e.getWhoClicked().openInventory(new SpecificCMDGUI().home.getInventory()); - }) - .define(13,LOGGED, e->{ - e.getWhoClicked().openInventory(new LoggedCMDGUI().home.getInventory()); - }) - .define(15,DANGEROUS, e->{ - e.getWhoClicked().openInventory(new DangerousCMDGUI().home.getInventory()); - }) - .build(); - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - MainGUI.verify((Player) e.getWhoClicked()); - } - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - } - - private static final ItemStack SPECIFIC = ItemBuilder.create() - .material(Material.SPECTRAL_ARROW) - .name(Text.color("&bSpecific Commands")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); - - private static final ItemStack LOGGED = ItemBuilder.create() - .material(Material.SPYGLASS) - .name(Text.color("&bLogged Commands")) - .lore(Text.color("&8&l➥&7 Modify this check")) - - .build(); - - private static final ItemStack DANGEROUS = ItemBuilder.create() - .material(Material.TNT) - .name(Text.color("&bDangerous Commands")) - .lore(Text.color("&8&l➥&7 Modify this check")) - .build(); -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.java deleted file mode 100644 index 2d6efa6..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBEditGUI.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class CBEditGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB Edit Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandBlockEdit.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockEdit.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandBlockEdit.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandBlockEdit.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandBlockEdit.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandBlockEdit.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandBlockEdit.enabled = !Sentinel.violationConfig.commandBlockEdit.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandBlockEdit.deop = !Sentinel.violationConfig.commandBlockEdit.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandBlockEdit.logToDiscord = !Sentinel.violationConfig.commandBlockEdit.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandBlockEdit.punish = !Sentinel.violationConfig.commandBlockEdit.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandBlockEdit.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandBlockEdit.punishmentCommands); - return; - } - Sentinel.violationConfig.commandBlockEdit.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.java deleted file mode 100644 index b02be97..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBExecuteGUI.java +++ /dev/null @@ -1,74 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.Text; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -public class CBExecuteGUI { - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB Whitelist")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack top = Items.RED; - if (Sentinel.violationConfig.commandBlockExecute.enabled) { - top = Items.GREEN; - } - - for (int i = 0; i < 9; i++) { - inv.setItem(i,top); - } - - inv.setItem(26,Items.BACK); - inv.setItem(4,Items.booleanItem(Sentinel.violationConfig.commandBlockExecute.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(11,Items.booleanItem(Sentinel.violationConfig.commandBlockExecute.destroyBlock,Items.configItem("Destroy",Material.NETHERITE_PICKAXE,"Destroy the offending command-block"))); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockExecute.attemptRestore,Items.configItem("Restore",Material.COMMAND_BLOCK,"Attempt to restore the block if a \nwhitelisted one exists at the location"))); - inv.setItem(15,Items.booleanItem(Sentinel.violationConfig.commandBlockExecute.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 4 -> { - Sentinel.violationConfig.commandBlockExecute.enabled = !Sentinel.violationConfig.commandBlockExecute.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 11 -> { - Sentinel.violationConfig.commandBlockExecute.destroyBlock = !Sentinel.violationConfig.commandBlockExecute.destroyBlock; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 13 -> { - Sentinel.violationConfig.commandBlockExecute.attemptRestore = !Sentinel.violationConfig.commandBlockExecute.attemptRestore; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 15 -> { - Sentinel.violationConfig.commandBlockExecute.logToDiscord = !Sentinel.violationConfig.commandBlockExecute.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - } - } -} - diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.java deleted file mode 100644 index 0d70a52..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCPlaceGUI.java +++ /dev/null @@ -1,119 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class CBMCPlaceGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB MC Place Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandBlockMinecartPlace.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartPlace.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandBlockMinecartPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandBlockMinecartPlace.enabled = !Sentinel.violationConfig.commandBlockMinecartPlace.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandBlockMinecartPlace.deop = !Sentinel.violationConfig.commandBlockMinecartPlace.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandBlockMinecartPlace.logToDiscord = !Sentinel.violationConfig.commandBlockMinecartPlace.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandBlockMinecartPlace.punish = !Sentinel.violationConfig.commandBlockMinecartPlace.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandBlockMinecartPlace.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandBlockMinecartPlace.punishmentCommands); - return; - } - Sentinel.violationConfig.commandBlockMinecartPlace.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.java deleted file mode 100644 index f47e415..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBMCUseGUI.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class CBMCUseGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB MC Use Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandBlockMinecartUse.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartUse.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandBlockMinecartUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandBlockMinecartUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandBlockMinecartUse.enabled = !Sentinel.violationConfig.commandBlockMinecartUse.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandBlockMinecartUse.deop = !Sentinel.violationConfig.commandBlockMinecartUse.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandBlockMinecartUse.logToDiscord = !Sentinel.violationConfig.commandBlockMinecartUse.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandBlockMinecartUse.punish = !Sentinel.violationConfig.commandBlockMinecartUse.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandBlockMinecartUse.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandBlockMinecartUse.punishmentCommands); - return; - } - Sentinel.violationConfig.commandBlockMinecartUse.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60,(e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.java deleted file mode 100644 index 9a665ce..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBPlaceGUI.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class CBPlaceGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB Place Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandBlockPlace.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockPlace.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandBlockPlace.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandBlockPlace.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandBlockPlace.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandBlockPlace.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandBlockPlace.enabled = !Sentinel.violationConfig.commandBlockPlace.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandBlockPlace.deop = !Sentinel.violationConfig.commandBlockPlace.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandBlockPlace.logToDiscord = !Sentinel.violationConfig.commandBlockPlace.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandBlockPlace.punish = !Sentinel.violationConfig.commandBlockPlace.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandBlockPlace.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandBlockPlace.punishmentCommands); - return; - } - Sentinel.violationConfig.commandBlockPlace.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.java deleted file mode 100644 index 1e633f2..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/CBUseGUI.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class CBUseGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 CB Use Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandBlockUse.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandBlockUse.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandBlockUse.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandBlockUse.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandBlockUse.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandBlockUse.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandBlockUse.enabled = !Sentinel.violationConfig.commandBlockUse.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandBlockUse.deop = !Sentinel.violationConfig.commandBlockUse.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandBlockUse.logToDiscord = !Sentinel.violationConfig.commandBlockUse.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandBlockUse.punish = !Sentinel.violationConfig.commandBlockUse.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandBlockUse.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandBlockUse.punishmentCommands); - return; - } - Sentinel.violationConfig.commandBlockUse.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.java deleted file mode 100644 index 56f723c..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/HotbarActionGUI.java +++ /dev/null @@ -1,121 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.AntiNukeGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class HotbarActionGUI { - - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 Creative Hotbar Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this:: mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new AntiNukeGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.creativeHotbarAction.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.creativeHotbarAction.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.creativeHotbarAction.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.creativeHotbarAction.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.creativeHotbarAction.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.creativeHotbarAction.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.creativeHotbarAction.enabled = !Sentinel.violationConfig.creativeHotbarAction.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.creativeHotbarAction.deop = !Sentinel.violationConfig.creativeHotbarAction.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.creativeHotbarAction.logToDiscord = !Sentinel.violationConfig.creativeHotbarAction.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.creativeHotbarAction.punish = !Sentinel.violationConfig.creativeHotbarAction.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.creativeHotbarAction.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.creativeHotbarAction.punishmentCommands); - return; - } - Sentinel.violationConfig.creativeHotbarAction.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.java deleted file mode 100644 index 9288a5a..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/DangerousCMDGUI.java +++ /dev/null @@ -1,132 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks.command; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.nuke.CommandGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class DangerousCMDGUI { - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 Dangerous Command Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new CommandGUI().home.getInventory()); - }) - .build(); - - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandExecute.dangerous.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandExecute.dangerous.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(2,Items.booleanItem(Sentinel.violationConfig.commandExecute.dangerous.deop,Items.configItem("De-Op",Material.END_CRYSTAL,"Remove the user's operator privileges"))); - inv.setItem(20,Items.booleanItem(Sentinel.violationConfig.commandExecute.dangerous.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(6,Items.booleanItem(Sentinel.violationConfig.commandExecute.dangerous.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"Run the punishment commands"))); - inv.setItem(24,Items.stringListItem(Sentinel.violationConfig.commandExecute.dangerous.punishmentCommands,Material.DIAMOND_AXE,"Punishment Commands","Commands that will be ran \nif this check is flagged.")); - inv.setItem(22,Items.stringListItem(Sentinel.violationConfig.commandExecute.dangerous.commands,Material.CRIMSON_HANGING_SIGN,"Commands","Commands that will flag this check.")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandExecute.dangerous.enabled = !Sentinel.violationConfig.commandExecute.dangerous.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 2 -> { - Sentinel.violationConfig.commandExecute.dangerous.deop = !Sentinel.violationConfig.commandExecute.dangerous.deop; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 20 -> { - Sentinel.violationConfig.commandExecute.dangerous.logToDiscord = !Sentinel.violationConfig.commandExecute.dangerous.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 6 -> { - Sentinel.violationConfig.commandExecute.dangerous.punish = !Sentinel.violationConfig.commandExecute.dangerous.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 24 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { - cfg.commandExecute.dangerous.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandExecute.dangerous.punishmentCommands); - return; - } - Sentinel.violationConfig.commandExecute.dangerous.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 22 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { - cfg.commandExecute.dangerous.commands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandExecute.dangerous.commands); - return; - } - Sentinel.violationConfig.commandExecute.dangerous.commands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.java deleted file mode 100644 index 0b2a53b..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/LoggedCMDGUI.java +++ /dev/null @@ -1,105 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks.command; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.nuke.CommandGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.List; -import java.util.function.BiConsumer; - -public class LoggedCMDGUI { - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 Logged Command Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new CommandGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack ring = Items.RED; - if (Sentinel.violationConfig.commandExecute.logged.enabled) { - ring = Items.GREEN; - } - - List ringList = List.of(3,4,5,12,14,21,22,23); - - for (Integer i : ringList) { - inv.setItem(i,ring); - } - - inv.setItem(26,Items.BACK); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandExecute.logged.enabled,Items.configItem("Check Toggle",Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(11,Items.booleanItem(Sentinel.violationConfig.commandExecute.logged.logToDiscord,Items.configItem("Log to Discord",Material.OAK_LOG,"If this check will log to discord"))); - inv.setItem(15,Items.stringListItem(Sentinel.violationConfig.commandExecute.logged.commands,Material.CRIMSON_HANGING_SIGN,"Commands","Commands that will flag this check")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 13 -> { - Sentinel.violationConfig.commandExecute.logged.enabled = !Sentinel.violationConfig.commandExecute.logged.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 11 -> { - Sentinel.violationConfig.commandExecute.logged.logToDiscord = !Sentinel.violationConfig.commandExecute.logged.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 15 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg,args) -> { - cfg.commandExecute.logged.commands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandExecute.logged.commands); - return; - } - Sentinel.violationConfig.commandExecute.logged.commands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - } - } - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } - -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.java b/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.java deleted file mode 100644 index 43af754..0000000 --- a/src/main/java/me/trouper/sentinel/server/gui/config/nuke/checks/command/SpecificCMDGUI.java +++ /dev/null @@ -1,109 +0,0 @@ -package me.trouper.sentinel.server.gui.config.nuke.checks.command; - -import io.github.itzispyder.pdk.commands.Args; -import io.github.itzispyder.pdk.plugin.gui.CustomGui; -import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater; -import io.papermc.paper.event.player.AsyncChatEvent; -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.config.ViolationConfig; -import me.trouper.sentinel.server.gui.Items; -import me.trouper.sentinel.server.gui.MainGUI; -import me.trouper.sentinel.server.gui.config.nuke.CommandGUI; -import me.trouper.sentinel.utils.ServerUtils; -import me.trouper.sentinel.utils.Text; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.function.BiConsumer; - -public class SpecificCMDGUI { - public final CustomGui home = CustomGui.create() - .title(Text.color("&6&lSentinel &8»&0 Specific Command Check")) - .size(27) - .onDefine(this::blankPage) - .defineMain(this::mainClick) - .define(26, Items.BACK, e->{ - e.getWhoClicked().openInventory(new CommandGUI().home.getInventory()); - }) - .build(); - - private void blankPage(Inventory inv) { - for (int i = 0; i < inv.getSize(); i++) { - inv.setItem(i,Items.BLANK); - } - - ItemStack top = Items.RED; - if (Sentinel.violationConfig.commandExecute.specific.enabled) { - top = Items.GREEN; - } - - for (int i = 0; i < 9; i++) { - inv.setItem(i,top); - } - - inv.setItem(26,Items.BACK); - inv.setItem(4,Items.booleanItem(Sentinel.violationConfig.commandExecute.specific.enabled,Items.configItem("Check Toggle", Material.CLOCK,"Enable/Disable this check entirely"))); - inv.setItem(11,Items.booleanItem(Sentinel.violationConfig.commandExecute.specific.punish,Items.configItem("Punish",Material.REDSTONE_TORCH,"If this check will run the punishment commands"))); - inv.setItem(13,Items.booleanItem(Sentinel.violationConfig.commandExecute.specific.logToDiscord,Items.configItem("Log",Material.OAK_LOG,"If this check will produce a log to discord"))); - inv.setItem(15,Items.stringListItem(Sentinel.violationConfig.commandExecute.specific.punishmentCommands,Material.DIAMOND_AXE,"Commands","Commands that will flag this check")); - } - - private void mainClick(InventoryClickEvent e) { - e.setCancelled(true); - if (!MainGUI.verify((Player) e.getWhoClicked())) return; - switch (e.getSlot()) { - case 4 -> { - Sentinel.violationConfig.commandExecute.specific.enabled = !Sentinel.violationConfig.commandExecute.specific.enabled; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 13 -> { - Sentinel.violationConfig.commandExecute.specific.logToDiscord = !Sentinel.violationConfig.commandExecute.specific.logToDiscord; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - case 11 -> { - Sentinel.violationConfig.commandExecute.specific.punish = !Sentinel.violationConfig.commandExecute.specific.punish; - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - - case 15 -> { - if (e.isLeftClick()) { - queuePlayer((Player) e.getWhoClicked(), (cfg, args) -> { - cfg.commandExecute.specific.punishmentCommands.add(args.getAll().toString()); - },"" + Sentinel.violationConfig.commandExecute.specific.punishmentCommands); - return; - } - Sentinel.violationConfig.commandExecute.specific.punishmentCommands.clear(); - blankPage(e.getInventory()); - Sentinel.violationConfig.save(); - } - } - } - - - public static ConfigUpdater updater = new ConfigUpdater<>(Sentinel.violationConfig); - - private void queuePlayer(Player player, BiConsumer action, String currentValue) { - MainGUI.awaitingCallback.add(player.getUniqueId()); - player.closeInventory(); - updater.queuePlayer(player, 20*60, (e)->{ - e.setCancelled(true); - return LegacyComponentSerializer.legacySection().serialize(e.message()); - }, (cfg, newValue) -> { - action.accept(cfg,new Args(newValue.split("\\s+"))); - cfg.save(); - player.sendMessage(Text.prefix("Value updated successfully")); - player.openInventory(home.getInventory()); - }); - player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue))); - } -} diff --git a/src/main/java/me/trouper/sentinel/server/gui/whitelist/WhitelistGUI.java b/src/main/java/me/trouper/sentinel/server/gui/whitelist/WhitelistGUI.java new file mode 100644 index 0000000..f0c6f03 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/server/gui/whitelist/WhitelistGUI.java @@ -0,0 +1,375 @@ +package me.trouper.sentinel.server.gui.whitelist; + +import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; +import io.github.itzispyder.pdk.plugin.gui.CustomGui; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.CommandBlockHolder; +import me.trouper.sentinel.server.gui.Items; +import me.trouper.sentinel.utils.ServerUtils; +import me.trouper.sentinel.utils.Text; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.*; +import java.util.stream.Collectors; + +public class WhitelistGUI { + + private static final Map currentPages = new HashMap<>(); + private static final Map> activeFilters = new HashMap<>(); + private static final Map chosenOperator = new HashMap<>(); + + public CustomGui createGUI(Player player) { + ServerUtils.verbose("Creating GUI for player: %s", player.getName()); + int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v)))); + return CustomGui.create() + .title(Text.color("&6&lCommand Blocks &7(" + getFilterCount(player) + " filters)")) + .size(54) + .onDefine(inv -> setupPage(player, inv)) + .defineMain(e -> { + e.setCancelled(true); + handleMainClick(player, e); + }) + .define(45, createNavigationItem("Previous",page - 1), e -> { + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,0.9F); + changePage(player, -1); + }) + .define(49, createFilterItem(player), e -> { + if (e.isShiftClick()) { + FilterOperator op = chosenOperator.computeIfAbsent(player.getUniqueId(),v-> FilterOperator.AND); + FilterOperator[] values = FilterOperator.values(); + chosenOperator.put(player.getUniqueId(),values[(op.ordinal() + 1) % values.length]); + e.getClickedInventory().setItem(e.getSlot(),createFilterItem(player)); + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.3F); + return; + } + openFilterMenu(player); + }) + .define(53, createNavigationItem("Next",page + 1), e -> { + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.1F); + changePage(player, 1); + }) + .build(); + } + + private void setupPage(Player player, Inventory inv) { + ServerUtils.verbose("Setting up page for player: %s", player.getName()); + int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v)))); + List filtered = filterEntries(player,chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND)); + ServerUtils.verbose("Current page: %d, Total entries: %d", page, filtered.size()); + + // Clear previous items + for (int i = 0; i < 45; i++) { + inv.setItem(i, null); + } + + // Add paginated items + for (int i = page * 45; i < (page + 1) * 45 && i < filtered.size(); i++) { + CommandBlockHolder holder = filtered.get(i); + inv.setItem(i % 45, createDisplayItem(holder)); + } + + // Add persistent bottom items + inv.setItem(45, createNavigationItem("Previous",realizePage(player, page - 1))); + inv.setItem(49, createFilterItem(player)); + inv.setItem(53, createNavigationItem("Next", realizePage(player,page + 1))); + } + + private void handleMainClick(Player player, InventoryClickEvent e) { + int slot = e.getSlot(); + if (slot >= 45) return; + if (e.getInventory().getItem(slot) == null) return; + + int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v)))); + List filtered = filterEntries(player,chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND)); + int index = page * 45 + slot; + + if (index < filtered.size()) { + CommandBlockHolder holder = filtered.get(index); + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_CHIME,1,0.8F); + openManagementMenu(player, holder); + } + } + + private ItemStack createDisplayItem(CommandBlockHolder holder) { + //ServerUtils.verbose("Creating Display Item for a command block owned by %s. Type is ", holder.owner(), holder.type()); + + Material type = holder.getType(); + + //ServerUtils.verbose("Type material is %s", type.name()); + + String name = holder.loc().isUUID() ? + "Minecart: " + holder.loc().toUIID() : + String.format("X: %d, Y: %d, Z: %d", + (int) holder.loc().x(), + (int) holder.loc().y(), + (int) holder.loc().z()); + + //ServerUtils.verbose("Name is %s", name); + + List lore = new ArrayList<>(); + lore.add(Text.color("&7Owner: " + Bukkit.getOfflinePlayer(holder.owner()).getName())); + //ServerUtils.verbose("Got owner"); + lore.add(Text.color("&7Command: &f" + holder.command())); + //ServerUtils.verbose("Got command"); + lore.add(Text.color("&7Type: &f" + holder.type())); + //ServerUtils.verbose("Got type"); + lore.add(Text.color("&7Whitelisted: " + (holder.isWhitelisted() ? "&aYes" : "&cNo"))); + //ServerUtils.verbose("Got whitelist status"); + lore.add(Text.color("&7Present: " + (holder.isPresent() ? "&aYes" : "&cNo"))); + //ServerUtils.verbose("Got Present Status"); + lore.add(""); + lore.add(Text.color("&eClick to manage!")); + + //ServerUtils.verbose("Successfully created item!"); + + return new ItemBuilder() + .material(type) + .name(Text.color("&b" + name)) + .lore(lore) + .build(); + } + + private void openManagementMenu(Player player, CommandBlockHolder holder) { + ServerUtils.verbose("Opening management menu for %s", holder.owner()); + boolean whitelisted = holder.isWhitelisted(); + + CustomGui menu = CustomGui.create() + .title(Text.color("&l ⬇ &6&lManaging Command Block")) + .size(9) + .defineMain(e -> e.setCancelled(true)) + .define(0,createDisplayItem(holder)) + .define(2, createActionItem(whitelisted ? "Un-Whitelist" : "Whitelist", whitelisted ? Material.BARRIER : Material.PAPER), e -> { + if (whitelisted) holder.removeFromWhitelist(); + else holder.addToWhitelist(); + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_PLING,1,1F); + openManagementMenu(player,holder); + }) + .define(3, createActionItem("Teleport", Material.ENDER_PEARL), e -> { + if (holder.loc().isUUID()) { + // Handle minecart teleport + Entity entity = Bukkit.getEntity(holder.loc().toUIID()); + if (entity == null) { + e.getInventory().setItem(e.getSlot(),ItemBuilder.create() + .material(Material.BARRIER) + .name("&cTeleport Unavailable") + .lore("&7This entity is not loaded.") + .build()); + player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_BASS,1,1F); + return; + } + player.teleport(entity.getLocation()); + } else { + player.teleport(holder.loc().translate()); + } + player.playSound(player.getLocation(),Sound.ENTITY_ENDERMAN_TELEPORT,1,0.5F); + player.closeInventory(); + }) + .define(4, createActionItem("Restore", Material.DISPENSER), e -> { + holder.restore(); + player.openInventory(createGUI(player).getInventory()); + player.playSound(player.getLocation(),Sound.BLOCK_AMETHYST_BLOCK_RESONATE,1,1F); + }) + .define(5, createActionItem("Destroy (Shift-Click)", Material.NETHERITE_PICKAXE), e -> { + if (!e.isShiftClick()) return; + holder.destroy(); + player.playSound(player.getLocation(),Sound.ENTITY_GENERIC_EXPLODE,1,2F); + player.openInventory(createGUI(player).getInventory()); + }) + .define(6,createActionItem("Take Ownership",Material.NAME_TAG), e -> { + CommandBlockHolder updated = new CommandBlockHolder( + player.getUniqueId().toString(), + holder.loc(), + holder.facing(), + holder.type(), + holder.auto(), + holder.conditional(), + holder.command() + ); + holder.destroy(); + if (whitelisted) updated.addToWhitelist(); + updated.restore(); + player.playSound(player.getLocation(),Sound.ENTITY_VILLAGER_TRADE,1,1F); + openManagementMenu(player,holder); + }) + .define(8,Items.BACK,e->{ + player.playSound(player.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F); + player.openInventory(createGUI(player).getInventory()); + }) + .build(); + + player.openInventory(menu.getInventory()); + } + + private ItemStack createActionItem(String name, Material mat) { + return new ItemBuilder() + .material(mat) + .name(Text.color("&b" + name)) + .lore(Text.color("&7Click to " + name.toLowerCase())) + .build(); + } + + // Filter handling methods + private enum Filter { + OWNER, CURRENT_WORLD, OTHER_OWNERS, + MINECART, REPEAT, CHAIN, IMPULSE, + WHITELISTED, NOT_WHITELISTED, NOT_PRESENT + } + + public enum FilterOperator { + AND, // All conditions must be met + OR, // At least one condition must be met + NAND, // At least one condition must NOT be met + XOR; // Exactly one condition must be met + + public boolean apply(boolean currentValue, boolean newCondition) { + return switch (this) { + case AND -> currentValue & newCondition; + case OR -> currentValue | newCondition; + case NAND -> !(currentValue & newCondition); + case XOR -> currentValue ^ newCondition; + }; + } + } + + private List filterEntries(Player player, FilterOperator operator) { + Set filters = activeFilters.computeIfAbsent(player.getUniqueId(), v -> new HashSet<>()); + ServerUtils.verbose("Filtering entries for %s. Current: ", player,filters.toString()); + return Sentinel.getInstance().getDirector().io.commandBlocks.existing.stream() + .filter(holder -> { + if (filters.isEmpty()) return true; + + boolean result = (operator == FilterOperator.AND); // AND starts true, OR starts false + + for (Filter filter : filters) { + boolean conditionMet = switch (filter) { + case OWNER -> holder.owner().equals(player.getUniqueId().toString()); + case CURRENT_WORLD -> holder.loc().world().equals(player.getWorld().getName()); + case OTHER_OWNERS -> !holder.owner().equals(player.getUniqueId().toString()); + case MINECART -> holder.getType().equals(Material.COMMAND_BLOCK_MINECART); + case REPEAT -> holder.getType().equals(Material.REPEATING_COMMAND_BLOCK); + case CHAIN -> holder.getType().equals(Material.CHAIN_COMMAND_BLOCK); + case IMPULSE -> holder.getType().equals(Material.COMMAND_BLOCK); + case WHITELISTED -> holder.isWhitelisted(); + case NOT_WHITELISTED -> !holder.isWhitelisted(); + case NOT_PRESENT -> !holder.isPresent(); + }; + + result = operator.apply(result, conditionMet); + + // Early exit for AND (false means no need to check further) + if (operator == FilterOperator.AND && !result) return false; + // Early exit for OR (true means we already pass) + if (operator == FilterOperator.OR && result) return true; + } + + return result; + }) + .collect(Collectors.toList()); + } + + private void openFilterMenu(Player player) { + ServerUtils.verbose("Creating filter menu for %s", player); + Set filters = activeFilters.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>()); + + CustomGui filterGui = CustomGui.create() + .title(Text.color("&6&lFilters")) + .size(27) + .defineMain(e -> e.setCancelled(true)) + .define(0, createFilterToggleItem("Your Blocks", Material.PLAYER_HEAD, filters.contains(Filter.OWNER)), + e -> toggleFilter(player, Filter.OWNER)) + .define(1, createFilterToggleItem("Other Owners", Material.SPYGLASS, filters.contains(Filter.OTHER_OWNERS)), + e -> toggleFilter(player, Filter.OTHER_OWNERS)) + .define(2, createFilterToggleItem("Current World", Material.TARGET, filters.contains(Filter.CURRENT_WORLD)), + e -> toggleFilter(player, Filter.CURRENT_WORLD)) + .define(3, createFilterToggleItem("Whitelisted Blocks", Material.PAPER, filters.contains(Filter.WHITELISTED)), + e -> toggleFilter(player, Filter.WHITELISTED)) + .define(4, createFilterToggleItem("Not Whitelisted Only", Material.BARRIER, filters.contains(Filter.NOT_WHITELISTED)), + e -> toggleFilter(player, Filter.NOT_WHITELISTED)) + .define(5, createFilterToggleItem("Missing Command Blocks", Material.GLASS, filters.contains(Filter.NOT_PRESENT)), + e -> toggleFilter(player, Filter.NOT_PRESENT)) + .define(6, createFilterToggleItem("Repeating Command Blocks", Material.REPEATING_COMMAND_BLOCK, filters.contains(Filter.REPEAT)), + e -> toggleFilter(player, Filter.REPEAT)) + .define(7, createFilterToggleItem("Chain Command Blocks", Material.CHAIN_COMMAND_BLOCK, filters.contains(Filter.CHAIN)), + e -> toggleFilter(player, Filter.CHAIN)) + .define(8, createFilterToggleItem("Impulse Command Blocks", Material.COMMAND_BLOCK, filters.contains(Filter.IMPULSE)), + e -> toggleFilter(player, Filter.IMPULSE)) + .define(9, createFilterToggleItem("Minecart Commands", Material.COMMAND_BLOCK_MINECART, filters.contains(Filter.MINECART)), + e -> toggleFilter(player, Filter.MINECART)) + .define(26, Items.BACK, + e-> { + player.playSound(player.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F); + player.openInventory(createGUI(player).getInventory()); + }) + .build(); + + player.openInventory(filterGui.getInventory()); + } + + private ItemStack createFilterToggleItem(String name, Material mat, boolean active) { + return new ItemBuilder() + .material(mat) + .name(Text.color((active ? "&a" : "&c") + name)) + .lore(Text.color("&7Click to " + (active ? "disable" : "enable"))) + .build(); + } + + private void toggleFilter(Player player, Filter filter) { + Set filters = activeFilters.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>()); + ServerUtils.verbose("%s is now toggling the %s filter. Current %s", player,filter,filters); + if (filters.contains(filter)) filters.remove(filter); + else filters.add(filter); + ServerUtils.verbose("Current filters for %s: %s", player,filters); + openFilterMenu(player); + } + + private int getFilterCount(Player player) { + return activeFilters.getOrDefault(player.getUniqueId(), new HashSet<>()).size(); + } + + private void changePage(Player player, int direction) { + int current = currentPages.getOrDefault(player.getUniqueId(), 0); + int newPage = realizePage(player, current + direction); + currentPages.put(player.getUniqueId(), newPage); + player.openInventory(createGUI(player).getInventory()); + } + + private int realizePage(Player player, int requested) { + int validRequested = Math.max(0, requested); + int totalEntries = filterEntries(player, + chosenOperator.computeIfAbsent(player.getUniqueId(), v -> FilterOperator.AND)).size(); + int maxPages = Math.max(0, Math.ceilDiv(totalEntries, 45) - 1); + return Math.min(validRequested, maxPages); + } + + private ItemStack createNavigationItem(String direction, int pageTo) { + return new ItemBuilder() + .material(Material.ARROW) + .name(Text.color("&b" + direction + "&7 Page")) + .lore(Text.color("&7 > &b" + pageTo)) + .build(); + } + + private ItemStack createFilterItem(Player player) { + List operatorList = new ArrayList<>(); + FilterOperator chosen = chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND); + for (FilterOperator value : FilterOperator.values()) { + if (value.equals(chosen)) operatorList.add(Text.color("&b&n" + value.name())); + else operatorList.add(Text.color("&b" + value.name())); + } + return new ItemBuilder() + .material(Material.HOPPER) + .name(Text.color("&6&lFilters")) + .lore(Text.color("&7Filters Selected: &e" + getFilterCount(player))) + .lore(Text.color("&7Shift-Click to cycle filter operator.")) + .lore(Text.color("&7Operator: ")) + .lore(operatorList) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/sentinel/startup/BackdoorDetection.java b/src/main/java/me/trouper/sentinel/startup/BackdoorDetection.java index 91ef272..82ce87e 100644 --- a/src/main/java/me/trouper/sentinel/startup/BackdoorDetection.java +++ b/src/main/java/me/trouper/sentinel/startup/BackdoorDetection.java @@ -6,14 +6,15 @@ import me.trouper.sentinel.utils.FileUtils; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; +import java.lang.System; import java.util.Arrays; -public class BackdoorDetection { +public final class BackdoorDetection { + + public void init() { + Sentinel.getInstance().getLogger().info("Backdoor Detection Enabled, server is running on " + FileUtils.whoAmI()); - public static void init() { - Sentinel.log.info("Backdoor Detection Enabled, server is running on " + FileUtils.whoAmI()); - - Sentinel.log.info("Searching for patchfile at " + Vaccine.PATCH_FILE.getAbsolutePath()); + Sentinel.getInstance().getLogger().info("Searching for patchfile at " + Vaccine.PATCH_FILE.getAbsolutePath()); File folder = new File(Vaccine.PATCH_FILE.getAbsolutePath().replace("\\.patched","").replace("/.patched","")); if (!Arrays.toString(folder.listFiles()).contains("\\.patched") && !Arrays.toString(folder.listFiles()).contains("/.patched")) { @@ -21,48 +22,48 @@ public class BackdoorDetection { makeSetupFile(); } else { if (Vaccine.PATCH_FILE.delete()) { - Sentinel.log.info("Patchfile verified successfully."); + Sentinel.getInstance().getLogger().info("Patchfile verified successfully."); } else { - Sentinel.log.info("Patchfile verified but not deleted."); + Sentinel.getInstance().getLogger().info("Patchfile verified but not deleted."); } } - if (Sentinel.mainConfig.backdoorDetection.setupMode && !Vaccine.SETUP_FILE.exists()) { + if (Sentinel.getInstance().getDirector().io.mainConfig.backdoorDetection.setupMode && !Vaccine.SETUP_FILE.exists()) { makeSetupFile(); } } - public static void patchServerJar() { + public void patchServerJar() { File serverJar = new File(FileUtils.whoAmI()); - Sentinel.log.info("Creating a server jar with custom startup..."); + Sentinel.getInstance().getLogger().info("Creating a server jar with custom startup..."); File tempJar = new File(serverJar.getPath() + "-patched"); try { - if (Injection.modifyJar(serverJar,Vaccine.class,tempJar)) { - Sentinel.log.info("Successfully created a server jar with backdoor protection. It is located at %s. Replace your server jar with it to enable executable integrity checks.".formatted(tempJar.getAbsolutePath())); + if (Sentinel.getInstance().getDirector().injection.modifyJar(serverJar,Vaccine.class,tempJar)) { + Sentinel.getInstance().getLogger().info("Successfully created a server jar with backdoor protection. It is located at %s. Replace your server jar with it to enable executable integrity checks.".formatted(tempJar.getAbsolutePath())); } else { - Sentinel.log.info("Failed to patch your server jar."); + Sentinel.getInstance().getLogger().info("Failed to patch your server jar."); } } catch (Exception e) { - Sentinel.log.info("Failed to patch your server jar."); + Sentinel.getInstance().getLogger().info("Failed to patch your server jar."); e.printStackTrace(); } } - public static void makeSetupFile() { - Sentinel.log.info("Detected setup mode to be enabled in config, adding setup file."); + public void makeSetupFile() { + Sentinel.getInstance().getLogger().info("Detected setup mode to be enabled in config, adding setup file."); try { if (Vaccine.SETUP_FILE.getParentFile().mkdirs() && Vaccine.SETUP_FILE.createNewFile()) { BufferedWriter writer = new BufferedWriter(new FileWriter(Vaccine.SETUP_FILE)); writer.write(Vaccine.PASSWORD); writer.flush(); - Sentinel.log.info("Successfully written to the file."); - Sentinel.log.info("Jar file verification will be reset next server reboot. You are now free to add plugins."); - if (Sentinel.mainConfig.backdoorDetection.keepSetupMode) return; - Sentinel.mainConfig.backdoorDetection.setupMode = false; - Sentinel.mainConfig.save(); + Sentinel.getInstance().getLogger().info("Successfully written to the file."); + Sentinel.getInstance().getLogger().info("Jar file verification will be reset next server reboot. You are now free to add plugins."); + if (Sentinel.getInstance().getDirector().io.mainConfig.backdoorDetection.keepSetupMode) return; + Sentinel.getInstance().getDirector().io.mainConfig.backdoorDetection.setupMode = false; + Sentinel.getInstance().getDirector().io.mainConfig.save(); } else { - Sentinel.log.info("Setup file already exists or could not be created."); + Sentinel.getInstance().getLogger().info("Setup file already exists or could not be created."); } } catch (Exception e) { System.err.println("Error enabling setup mode."); diff --git a/src/main/java/me/trouper/sentinel/startup/IndirectLaunch.java b/src/main/java/me/trouper/sentinel/startup/IndirectLaunch.java deleted file mode 100644 index f8acaf6..0000000 --- a/src/main/java/me/trouper/sentinel/startup/IndirectLaunch.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.trouper.sentinel.startup; - -import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.utils.ServerUtils; - -public class IndirectLaunch { - public static void launch() { - Sentinel.getInstance().ip = ServerUtils.getPublicIPAddress(); - Sentinel.getInstance().port = ServerUtils.getPort(); - Sentinel.getInstance().nonce = Auth.getNonce(); - - Sentinel.log.info("Getting plugin file"); - - Sentinel.log.info("Reading Persistent files..."); - - Sentinel.getInstance().loadConfig(); - - Sentinel.log.info("Language Status: (%s)".formatted(Sentinel.lang.brokenLang)); - - Sentinel.log.info("Initializing Auth Identifier"); - - Sentinel.getInstance().identifier = Auth.getServerID(); - - Load.load(Sentinel.getInstance().license,Sentinel.getInstance().identifier, true); - } -} diff --git a/src/main/java/me/trouper/sentinel/startup/Injection.java b/src/main/java/me/trouper/sentinel/startup/Injection.java index 59d3426..d30c9be 100644 --- a/src/main/java/me/trouper/sentinel/startup/Injection.java +++ b/src/main/java/me/trouper/sentinel/startup/Injection.java @@ -3,17 +3,15 @@ package me.trouper.sentinel.startup; import org.objectweb.asm.*; import java.io.*; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; -public class Injection { +public final class Injection { - public static boolean modifyJar(File inputJar, Class runnableClass, File outputJar) { + public boolean modifyJar(File inputJar, Class runnableClass, File outputJar) { // Read the JAR file's manifest try { JarFile jarFile = new JarFile(inputJar); @@ -50,7 +48,7 @@ public class Injection { return true; } - private static void addRunnableClassToJar(JarFile jarFile, JarOutputStream jarOut, Class runnableClass) throws Exception { + private void addRunnableClassToJar(JarFile jarFile, JarOutputStream jarOut, Class runnableClass) throws Exception { // Check if the Runnable class is already present in the JAR String runnableClassPath = runnableClass.getName().replace('.', '/') + ".class"; if (isClassInJar(jarFile, runnableClassPath)) { diff --git a/src/main/java/me/trouper/sentinel/startup/Telemetry.java b/src/main/java/me/trouper/sentinel/startup/Telemetry.java index 0297d90..2bbc7e2 100644 --- a/src/main/java/me/trouper/sentinel/startup/Telemetry.java +++ b/src/main/java/me/trouper/sentinel/startup/Telemetry.java @@ -1,34 +1,26 @@ package me.trouper.sentinel.startup; import io.github.itzispyder.pdk.utils.discord.DiscordEmbed; -import io.github.itzispyder.pdk.utils.misc.Timer; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; -import me.trouper.sentinel.utils.CipherUtils; import me.trouper.sentinel.utils.trees.EmbedFormatter; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; import java.net.URI; -import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.util.concurrent.TimeoutException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -public class Telemetry { +public final class Telemetry { private static String webhook; private static final String API_URL = "http://api.trouper.me:8080/api/webhook"; private static final String API_TOKEN = "this-really-isnt-needed"; - public static boolean report(String title, String reason) { + public boolean report(String title, String reason) { try { + if (!Sentinel.getInstance().getDirector().io.mainConfig.telemetry) return false; if (webhook == null || webhook.isBlank()) webhook = fetchTelemetryHook(); DiscordEmbed embed = new DiscordEmbed.Builder() @@ -51,8 +43,8 @@ public class Telemetry { """.formatted( Sentinel.getInstance().license, Sentinel.getInstance().nonce, - MainConfig.username, - MainConfig.user, + Sentinel.getInstance().getDirector().io.mainConfig.username, + Sentinel.getInstance().getDirector().io.mainConfig.user, Sentinel.getInstance().identifier, Sentinel.getInstance().ip, Sentinel.getInstance().port, @@ -68,7 +60,7 @@ public class Telemetry { return true; } - public static String fetchTelemetryHook() throws Exception { + public String fetchTelemetryHook() throws Exception { HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); diff --git a/src/main/java/me/trouper/sentinel/startup/Vaccine.java b/src/main/java/me/trouper/sentinel/startup/Vaccine.java index ba815c0..77dd62b 100644 --- a/src/main/java/me/trouper/sentinel/startup/Vaccine.java +++ b/src/main/java/me/trouper/sentinel/startup/Vaccine.java @@ -1,7 +1,5 @@ package me.trouper.sentinel.startup; -import org.apache.commons.lang3.StringUtils; - import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; @@ -13,112 +11,12 @@ import java.util.HashMap; import java.util.Map; public class Vaccine implements Runnable { - /* - Below is a discussion of several flaws in the design and implementation of this “Vaccine” class. In short, while the idea is to “lock down” the server’s jar files, there are several ways an attacker (or even an inadvertent change) could cause the protection to fail or be bypassed. Here are some of the main issues: ---- - -### 1. Use of MD5 for Integrity Checking - -- **Weak Hash Algorithm:** - The code uses MD5 to calculate file checksums. MD5 is now considered cryptographically broken and subject to collision attacks. An attacker with the skills to create a jar file that collides with a legitimate MD5 hash might be able to bypass the integrity check. - -- **Collision Attacks:** - Since MD5 is not collision resistant, it may be possible to generate two different jar files that yield the same MD5 hash. This makes the “fingerprint” of a jar file untrustworthy. - ---- - -### 2. Hard-Coded Password and Key Management - -- **Static Password:** - The password `"SentinelAntiNuke"` is hard-coded. An attacker who reverse engineers your plugin or reads the source (or decompiles the bytecode) will know the “secret” used for both the setup file check and for encrypting/decrypting the checksum file. - -- **Setup Mode Abuse:** - The existence of a “setup” file (with the same hard-coded password inside) causes the plugin to clear the existing checksums and re-register all jar files. An attacker who can write to the server directory could create such a file (or modify it) and force the plugin to re-register even malicious files. - ---- - -### 3. Insecure Encryption Practices - -- **AES in ECB Mode:** - In your `getCipher` method you call `Cipher.getInstance("AES")`, which in many Java versions defaults to `"AES/ECB/PKCS5Padding"`. ECB (Electronic Codebook) mode is not semantically secure – it does not use an IV, and identical blocks of plaintext result in identical ciphertext. While you are not encrypting extremely sensitive data here, it is still not a best practice. - -- **Key Derivation:** - The key is derived by taking the SHA‑256 hash of the password and using the first 16 bytes. This is not as robust as using a proper key derivation function (like PBKDF2) with a salt and many iterations. Although the password is fixed, this makes it trivial for an attacker to derive the same key. - -- **Checksum File Tampering:** - The checksum file (`.checksums.lock`) is encrypted with a key that is easily re-derived from the hard-coded password. An attacker who can access the filesystem can decrypt, modify, and re-encrypt this file to “legitimize” malicious jar files. - ---- - -### 4. Mapping by File Name Only - -- **Insufficient Uniqueness:** - The plugin uses the jar’s filename (using `file.getName()`) as the key in the checksum map. This means that if there are two jar files with the same name in different directories, they will collide in the map. An attacker might take advantage of this by placing a malicious jar in a different directory under a known-good name. - -- **Case Sensitivity Issues:** - The code checks for files ending in `".jar"` (a case‑sensitive match). A file named `"plugin.JAR"` (with different casing) would be skipped by the integrity check. - ---- - -### 5. Deserialization of Encrypted Data - -- **Use of Object Serialization:** - The checksum file is stored as a serialized Java object. Even though it is encrypted, once an attacker can compute the key (which they easily can due to the hard-coded password), they might be able to craft malicious serialized data. In Java, deserialization of untrusted data can lead to remote code execution if there is a gadget chain available. - ---- - -### 6. File Operation Issues - -- **Renaming for Quarantine:** - When a jar file fails the checksum test, the plugin attempts to “quarantine” it by renaming it with a `.quarantined` suffix. However, the code does not check whether the rename operation succeeded. If it fails, the jar might still be loaded. - -- **Recursive Directory Traversal:** - The recursion into subdirectories does not protect against cycles (e.g. via symbolic links). Although this is more of a robustness/usability concern than a direct security issue, it could be exploited in some situations. - ---- - -### 7. General Trust Model Problems - -- **Reliance on the Filesystem:** - The entire scheme is based on file checksums stored on disk. If an attacker already has the ability to modify files on the server, they can simply change the checksum file (or the jar files and then re-run the setup process) to bypass your integrity checks. - -- **No External Trust Anchor:** - There is no digital signature or external verification. Everything depends on locally stored values that, once known, are trivial for an attacker to forge. - ---- - -### **Summary** - -While the intent of “injecting” code to check MD5 sums of jar files might seem to raise the bar against backdoors, the design is fundamentally flawed: - -- **MD5 is too weak** to trust for integrity checking. -- **A hard-coded password** means that the “secret” is public to anyone who looks at the code. -- **The encryption method (AES in ECB mode, with a trivial key derivation)** is not sufficient to protect the checksum file from tampering. -- **Mapping by just filename** (with case‑sensitivity issues) opens up additional attack vectors. -- **The re‑registration process** (triggered by a setup file) can be abused by an attacker with filesystem access. - -Any attacker who has access to the server’s filesystem (or who can upload files) can defeat these measures by simply regenerating the checksums after introducing malicious code. - ---- - -### **Recommendations** - -- **Use a stronger hash:** Replace MD5 with SHA‑256 (or better) for file integrity. -- **Improve key management:** Avoid hard-coding passwords; consider using a secure configuration that isn’t embedded in code. -- **Use a secure cipher mode:** Switch from ECB to a mode such as CBC or GCM and use a proper IV. -- **Include full paths:** When mapping files, use their canonical paths (or a similar unique identifier) rather than just the filename. -- **Avoid unsafe deserialization:** If you must persist data, use a safer data format (such as JSON or XML) and validate it. -- **Add a digital signature:** Instead of (or in addition to) simple checksums, sign your jar files with a trusted certificate. - -By addressing these issues, you would significantly improve the robustness of your server’s integrity checking mechanism. - */ - - public static final String PASSWORD = "%%__TIMESTAMP__%%"; // This can be replaced with a dynamic password input method + public static final String PASSWORD = "%%__TIMESTAMP__%%"; private static final File FOLDER = new File(".sentinel/"); private static final File CHECKSUM_FILE = new File(FOLDER, ".checksums.lock"); - public static final File SETUP_FILE = new File(FOLDER, ".checksums.setup"); // Setup file to reset checksums - public static final File PATCH_FILE = new File(FOLDER, ".patched"); // PatchFile name + public static final File SETUP_FILE = new File(FOLDER, ".checksums.setup"); + public static final File PATCH_FILE = new File(FOLDER, ".patched"); private static Map fileChecksums = new HashMap<>(); diff --git a/src/main/java/me/trouper/sentinel/startup/Auth.java b/src/main/java/me/trouper/sentinel/startup/drm/Auth.java similarity index 75% rename from src/main/java/me/trouper/sentinel/startup/Auth.java rename to src/main/java/me/trouper/sentinel/startup/drm/Auth.java index 87d64db..8dc55db 100644 --- a/src/main/java/me/trouper/sentinel/startup/Auth.java +++ b/src/main/java/me/trouper/sentinel/startup/drm/Auth.java @@ -1,13 +1,10 @@ -package me.trouper.sentinel.startup; +package me.trouper.sentinel.startup.drm; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.AdvancedConfig; -import me.trouper.sentinel.utils.CipherUtils; -import me.trouper.sentinel.utils.MathUtils; -import me.trouper.sentinel.utils.ServerUtils; -import org.bukkit.Bukkit; +import me.trouper.sentinel.utils.HashUtils; import java.io.BufferedReader; import java.io.IOException; @@ -19,9 +16,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class Auth { +public final class Auth { - public static String authorize(String license, String identifier) { + public String authorize(String license, String identifier) { + if (true) { + return "AUTHORIZED"; + } Map> licenses = getLicenseList(); if (licenses == null) return "ERROR"; @@ -43,11 +43,11 @@ public class Auth { * This should be the last auth variable called. * @return the unique identifier of the server */ - public static String getServerID() { - return CipherUtils.SHA256(Sentinel.getInstance().nonce + Sentinel.getInstance().ip + Sentinel.getInstance().port); + public String getServerID() { + return HashUtils.SHA256(Sentinel.getInstance().nonce + Sentinel.getInstance().ip + Sentinel.getInstance().port); } - public static Map> getLicenseList() { + public Map> getLicenseList() { try { String urlString = "http://api.trouper.me:8080/sentinel"; URL url = new URL(urlString); @@ -76,11 +76,11 @@ public class Auth { } } - public static String getNonce() { - return CipherUtils.MD5(AdvancedConfig.nonce); + public String getNonce() { + return HashUtils.MD5(Sentinel.getInstance().getDirector().io.advConfig.nonce); } - public static String getLicenseKey() { - return Sentinel.mainConfig.plugin.license; + public String getLicenseKey() { + return Sentinel.getInstance().getDirector().io.mainConfig.plugin.license; } } diff --git a/src/main/java/me/trouper/sentinel/startup/Load.java b/src/main/java/me/trouper/sentinel/startup/drm/Loader.java similarity index 51% rename from src/main/java/me/trouper/sentinel/startup/Load.java rename to src/main/java/me/trouper/sentinel/startup/drm/Loader.java index 3e850ac..ecfd659 100644 --- a/src/main/java/me/trouper/sentinel/startup/Load.java +++ b/src/main/java/me/trouper/sentinel/startup/drm/Loader.java @@ -1,20 +1,38 @@ -package me.trouper.sentinel.startup; +package me.trouper.sentinel.startup.drm; import io.github.itzispyder.pdk.utils.SchedulerUtils; import me.trouper.sentinel.Sentinel; import me.trouper.sentinel.data.config.MainConfig; import me.trouper.sentinel.server.commands.*; -import me.trouper.sentinel.server.events.*; +import me.trouper.sentinel.server.events.admin.AntiBanEvents; +import me.trouper.sentinel.server.events.admin.BlockDisplayHideEvent; +import me.trouper.sentinel.server.events.admin.WandEvents; +import me.trouper.sentinel.server.events.violations.blocks.command.*; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.jigsaw.JigsawBlockUse; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockBreak; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockPlace; +import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBlockUse; +import me.trouper.sentinel.server.events.violations.command.DangerousCommand; +import me.trouper.sentinel.server.events.violations.command.LoggedCommand; +import me.trouper.sentinel.server.events.violations.command.SpecificCommand; +import me.trouper.sentinel.server.events.violations.players.*; +import me.trouper.sentinel.server.events.violations.whitelist.CommandBlockExecute; +import me.trouper.sentinel.server.events.extras.ShadowRealmEvents; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartBreak; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartPlace; +import me.trouper.sentinel.server.events.violations.entities.CommandMinecartUse; import me.trouper.sentinel.server.functions.chatfilter.profanity.ProfanityFilter; import me.trouper.sentinel.server.functions.chatfilter.spam.SpamFilter; import me.trouper.sentinel.utils.Text; import org.bukkit.Bukkit; -public class Load { +public final class Loader { - public static boolean lite = false; + private boolean lite = false; - public static String liteMode = Text.color(""" + public static final String LITE_MODE = Text.color(""" &8]=-&f Welcome to &d&lSentinel &7|&f Anti-Nuke &8-=[ &7The plugin is currently loaded in &clite&7 mode. @@ -39,59 +57,60 @@ public class Load { &8- &7DM &b@obvwolf&7 on discord and lets make a deal! """.formatted(Sentinel.getInstance().license,Sentinel.getInstance().identifier, MainConfig.username)); - public static boolean load(String license, String identifier, boolean coldStart) { - Sentinel.log.info("\n]====---- Requesting Authentication ----====[ \n- License Key: %s\n- Server ID: %s\n".formatted(license,identifier)); + public boolean load(String license, String identifier, boolean coldStart) { + Sentinel.getInstance().getLogger().info("\n]====---- Requesting Authentication ----====[ \n- License Key: %s\n- Server ID: %s\n".formatted(license,identifier)); try { - Sentinel.log.info("Auth Requested..."); - switch (Auth.authorize(license,identifier)) { + Sentinel.getInstance().getLogger().info("Auth Requested..."); + switch (Sentinel.getInstance().getDirector().auth.authorize(license,identifier)) { case "AUTHORIZED" -> { - Sentinel.log.info("\n]======----- Auth Success! -----======["); + Sentinel.getInstance().getLogger().info("\n]======----- Auth Success! -----======["); startup(coldStart); return true; } case "MINEHUT" -> { - boolean minehutStatus = Telemetry.report("Dynamic IP server has authorized.","Success."); + boolean minehutStatus = Sentinel.getInstance().getDirector().telemetry.report("Dynamic IP server has authorized.","Success."); if (minehutStatus) { - Sentinel.log.info("Dynamic IP auth Success!"); + Sentinel.getInstance().getLogger().info("Dynamic IP auth Success!"); startup(coldStart); return true; } else { - Sentinel. log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this."); + Sentinel.getInstance().getLogger().info("Dynamic IP Failure. Make sure telemetry is enabled in main-config.json. If it still doesn't work, contact a developer."); if (coldStart) liteStart("How is this even possible?"); } } case "INVALID-ID" -> { - Sentinel.log.info("Authentication Failure, You have not whitelisted this server ID yet."); + Sentinel.getInstance().getLogger().info("Authentication Failure, You have not whitelisted this server ID yet."); if (coldStart) liteStart("They have not whitelisted their server ID yet. (License exists, no ID)"); } case "UNREGISTERED" -> { - Sentinel.log.warning("Authentication Failure, YOU SHALL NOT PASS! License: %s Server ID: %s".formatted(license,identifier)); + Sentinel.getInstance().getLogger().warning("Authentication Failure, YOU SHALL NOT PASS! License: %s Server ID: %s".formatted(license,identifier)); if (coldStart) liteStart("They do not have a license key"); } case "ERROR" -> { - Sentinel.log.warning("Hmmmmmm thats not right... License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,identifier)); + Sentinel.getInstance().getLogger().warning("Hmmmmmm thats not right... License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,identifier)); if (coldStart) liteStart("An expected error occurred which prevented them from launching"); } default -> { - Sentinel.log.warning("Achievement unlocked: How did we get here? License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,identifier)); + Sentinel.getInstance().getLogger().warning("Achievement unlocked: How did we get here? License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,identifier)); if (coldStart) liteStart("An unexpected error occured which prevented them from launching"); } } } catch (Exception e) { e.printStackTrace(); - Sentinel.log.info("WTFFFF ARE YOU DOING MAN??????"); + Sentinel.getInstance().getLogger().info("WTFFFF ARE YOU DOING MAN??????"); if (coldStart) liteStart("An exception was thrown, then caught."); } return false; + } - public static void liteStart(String reason) { - lite = true; - Telemetry.report("Server has launched in lite mode",reason); + public void liteStart(String reason) { + setLite(true); + Sentinel.getInstance().getDirector().telemetry.report("Server has launched in lite mode",reason); new SentinelCommand().register(); - Sentinel.log.info(""" + Sentinel.getInstance().getLogger().info(""" Finished! ____ __ ___ \s /\\ _`\\ /\\ \\__ __ /\\_ \\ \s @@ -105,18 +124,18 @@ public class Load { SchedulerUtils.repeat(20*60,()->{ - if (lite) { - Sentinel.log.info(Text.removeColors(Load.liteMode)); + if (Sentinel.getInstance().getDirector().loader.isLite()) { + Sentinel.getInstance().getLogger().info(Text.removeColors(Loader.LITE_MODE)); } }); } - public static void startup(boolean coldStart) { - Sentinel.log.info("\n]======----- Loading Sentinel! -----======["); - lite = false; + public void startup(boolean coldStart) { + Sentinel.getInstance().getLogger().info("\n]======----- Loading Sentinel! -----======["); + setLite(false); // Plugin startup logic - Sentinel.log.info("Starting Up! (%s)...".formatted(Sentinel.getInstance().getDescription().getVersion())); + Sentinel.getInstance().getLogger().info("Starting Up! (%s)...".formatted(Sentinel.getInstance().getDescription().getVersion())); // Commands if (coldStart) new SentinelCommand().register(); @@ -124,27 +143,43 @@ public class Load { new ReplyCommand().register(); new ReopCommand().register(); new CallbackCommand().register(); + new ExtraCommand().register(); // Events + new AntiBanEvents().register(); new CommandBlockEdit().register(); new CommandBlockExecute().register(); - new CommandBlockMinecartPlace().register(); - new CommandBlockMinecartUse().register(); + new CommandMinecartPlace().register(); + new CommandMinecartUse().register(); + new CommandMinecartBreak().register(); new CommandBlockPlace().register(); new CommandBlockUse().register(); + new CommandBlockBreak().register(); new ChatEvent().register(); - new CommandExecute().register(); + new DangerousCommand().register(); + new LoggedCommand().register(); + new SpecificCommand().register(); new CreativeHotbar().register(); new TrapCommand().register(); - new PluginCloakingEvent().register(); + new PluginCloakingEvents().register(); + new WandEvents().register(); + new JigsawBlockBreak().register(); + new JigsawBlockPlace().register(); + new JigsawBlockUse().register(); + new StructureBlockBreak().register(); + new StructureBlockUse().register(); + new StructureBlockPlace().register(); + new ShadowRealmEvents().register(); + new BlockDisplayHideEvent().register(); // Scheduled timers Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), SpamFilter::decayHeat,0, 20); Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), ProfanityFilter::decayScore,0,1200); + Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), WandEvents::handleDisplay,0,1); + + if (Sentinel.getInstance().getDirector().io.mainConfig.backdoorDetection.enabled) Sentinel.getInstance().getDirector().backdoorDetection.init(); - if (Sentinel.mainConfig.backdoorDetection.enabled) BackdoorDetection.init(); - - Sentinel.log.info(""" + Sentinel.getInstance().getLogger().info(""" Finished! ____ __ ___ \s /\\ _`\\ /\\ \\__ __ /\\_ \\ \s @@ -155,4 +190,12 @@ public class Load { \\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/ ]====---- Advanced Anti-Grief & Chat Filter ----====["""); } + + public boolean isLite() { + return lite; + } + + public void setLite(boolean lite) { + this.lite = lite; + } } diff --git a/src/main/java/me/trouper/sentinel/utils/CipherUtils.java b/src/main/java/me/trouper/sentinel/utils/CipherUtils.java deleted file mode 100644 index c20a039..0000000 --- a/src/main/java/me/trouper/sentinel/utils/CipherUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -package me.trouper.sentinel.utils; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.File; -import java.io.FileInputStream; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; - -public class CipherUtils { - private static final String secretKey = "GG8T885O4Yd/86OMVFdL0w=="; // 16, 24, or 32 bytes - private static final String algorithm = "AES"; - public static String encrypt(String strToEncrypt) { - try { - SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); - Cipher cipher = Cipher.getInstance(algorithm); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); - byte[] encryptedBytes = cipher.doFinal(strToEncrypt.getBytes()); - return Base64.getEncoder().encodeToString(encryptedBytes); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static String decrypt(String strToDecrypt) { - try { - SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); - Cipher cipher = Cipher.getInstance(algorithm); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); - byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)); - return new String(decryptedBytes); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static String getFileHash(File file) { - try { - // Create a MessageDigest instance for SHA-256 - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - - // Read the file's content - FileInputStream fis = new FileInputStream(file); - byte[] byteArray = new byte[1024]; - int bytesRead; - - // Update the MessageDigest with the file's data - while ((bytesRead = fis.read(byteArray)) != -1) { - digest.update(byteArray, 0, bytesRead); - } - - fis.close(); - - // Get the hash's bytes - byte[] hashBytes = digest.digest(); - - // Convert the hash's bytes to a hex string - StringBuilder hexString = new StringBuilder(); - for (byte b : hashBytes) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) hexString.append('0'); - hexString.append(hex); - } - - return hexString.toString(); - - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public static String SHA256(String input) { - try { - - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - - - byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); - - StringBuilder hexString = new StringBuilder(2 * encodedHash.length); - for (byte b : encodedHash) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - - return hexString.toString(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } - } - - public static String MD5(String input) { - try { - - MessageDigest digest = MessageDigest.getInstance("MD5"); - - - byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); - - StringBuilder hexString = new StringBuilder(2 * encodedHash.length); - for (byte b : encodedHash) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - - return hexString.toString(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/src/main/java/me/trouper/sentinel/utils/DisplayUtils.java b/src/main/java/me/trouper/sentinel/utils/DisplayUtils.java new file mode 100644 index 0000000..7bf1efe --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/DisplayUtils.java @@ -0,0 +1,228 @@ +package me.trouper.sentinel.utils; + +import io.github.itzispyder.pdk.utils.misc.Randomizer; +import me.trouper.sentinel.Sentinel; +import me.trouper.sentinel.data.types.Selection; +import me.trouper.sentinel.utils.display.BlockDisplayRaytracer; +import org.bukkit.*; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.*; + +public final class DisplayUtils { + public static void drawSelection(Player player, Selection selection) { + if (selection == null || !selection.isComplete()) return; + + Location pos1 = selection.getPos1(); + Location pos2 = selection.getPos2(); + + World world = pos1.getWorld(); + + int minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); + int minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); + int minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); + int maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); + int maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()); + int maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); + + // Define the 12 edges + Location[] edgeStart = { + new Location(world, minX, minY, minZ), new Location(world, maxX, minY, minZ), + new Location(world, minX, minY, maxZ), new Location(world, maxX, minY, maxZ), + + new Location(world, minX, maxY, minZ), new Location(world, maxX, maxY, minZ), + new Location(world, minX, maxY, maxZ), new Location(world, maxX, maxY, maxZ), + + new Location(world, minX, minY, minZ), new Location(world, minX, maxY, minZ), + new Location(world, maxX, minY, minZ), new Location(world, maxX, maxY, minZ), + + new Location(world, minX, minY, maxZ), new Location(world, minX, maxY, maxZ), + new Location(world, maxX, minY, maxZ), new Location(world, maxX, maxY, maxZ) + }; + + Location[] edgeEnd = { + new Location(world, maxX, minY, minZ), new Location(world, maxX, minY, maxZ), + new Location(world, minX, minY, maxZ), new Location(world, minX, minY, minZ), + + new Location(world, maxX, maxY, minZ), new Location(world, maxX, maxY, maxZ), + new Location(world, minX, maxY, maxZ), new Location(world, minX, maxY, minZ), + + new Location(world, minX, maxY, minZ), new Location(world, minX, maxY, minZ), + new Location(world, maxX, maxY, minZ), new Location(world, maxX, maxY, minZ), + + new Location(world, minX, maxY, maxZ), new Location(world, minX, maxY, maxZ), + new Location(world, maxX, maxY, maxZ), new Location(world, maxX, maxY, maxZ) + }; + + for (int i = 0; i < edgeStart.length; i++) { + BlockDisplayRaytracer.trace(Material.LIGHT_BLUE_STAINED_GLASS,edgeStart[i],edgeEnd[i],0.2,20,List.of(player)); + + } + } + + + public static final Function> PLAYER_PARTICLE_FACTORY = particle -> (p,l) -> p.spawnParticle(particle, l, 1, 0, 0, 0, 0); + + public static final BiFunction> PLAYER_DUST_PARTICLE_FACTORY = (color, thickness) -> { + Particle.DustOptions dust = new Particle.DustOptions(color, thickness); + return (p,l) -> p.spawnParticle(Particle.DUST, l, 1, 0, 0, 0, 0, dust); + }; + + public static final Function> PLAYER_FLAME_PARTICLE_FACTORY = soul -> { + Particle flame = soul ? Particle.SOUL_FIRE_FLAME : Particle.FLAME; + return (p,l) -> p.spawnParticle(flame, l, 1, 0, 0, 0, 0); + }; + + public static final Function> PARTICLE_FACTORY = particle -> l -> l.getWorld().spawnParticle(particle, l, 1, 0, 0, 0, 0); + + public static final BiFunction> DUST_PARTICLE_FACTORY = (color, thickness) -> { + Particle.DustOptions dust = new Particle.DustOptions(color, thickness); + return l -> l.getWorld().spawnParticle(Particle.DUST, l, 1, 0, 0, 0, 0, dust); + }; + + public static final Function> FLAME_PARTICLE_FACTORY = soul -> { + Particle flame = soul ? Particle.SOUL_FIRE_FLAME : Particle.FLAME; + return l -> l.getWorld().spawnParticle(flame, l, 1, 0, 0, 0, 0); + }; + + public static void ring(Location loc, double radius, Color color, float thickness) { + ring(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness)); + } + + public static void ring(Location loc, double radius, Consumer action) { + for (int theta = 0; theta < 360; theta += 10) { + double x = Math.cos(Math.toRadians(theta)) * radius; + double z = Math.sin(Math.toRadians(theta)) * radius; + Location newLoc = loc.clone().add(x, 0, z); + action.accept(newLoc); + } + } + + public static void wave(Location loc, double radius, Color color, float thickness, double gap) { + wave(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness), gap); + } + + public static void wave(Location loc, double radius, Consumer action, double gap) { + AtomicReference i = new AtomicReference<>(gap); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Sentinel.getInstance(), () -> { + if (i.get() >= radius) { + return; + } + ring(loc, i.get(), action); + i.set(i.get() + gap); + }, 0, 1); + } + + public static void wave(Location center, double radius, double frequency, long interval, Consumer onPoint) { + AtomicReference currentRadius = new AtomicReference<>(0.0); + + Bukkit.getScheduler().scheduleSyncRepeatingTask(Sentinel.getInstance(), () -> { + if (currentRadius.get() <= radius) { + ring(center, currentRadius.get(), onPoint, (point, angle) -> true); + currentRadius.set(currentRadius.get() + frequency); + } + }, 0, interval); + } + + + public static void disc(Location loc, double radius, Consumer action, double gap) { + for (double i = gap; i < radius; i += gap) { + ring(loc, i, action); + } + } + + public static void helix(Location loc, double radius, Consumer action, double gap, int height) { + int theta = 0; + for (double y = 0; y <= height; y += gap) { + double x = Math.cos(Math.toRadians(theta)) * radius; + double z = Math.sin(Math.toRadians(theta)) * radius; + + Location newLoc = loc.clone().add(x, y, z); + action.accept(newLoc); + theta += 10; + } + } + + public static void vortex(Location loc, double radius, Consumer action, double gapH, double gapV, int height) { + double r = radius; + int theta = 0; + for (double y = 0; y <= height; y += gapV) { + double x = Math.cos(Math.toRadians(theta)) * r; + double z = Math.sin(Math.toRadians(theta)) * r; + + Location newLoc = loc.clone().add(x, y, z); + action.accept(newLoc); + r += gapH; + theta += 10; + } + } + + public static void beam(Location loc, Consumer action, double gap, int height) { + for (double y = 0; y <= height; y += gap) { + Location newLoc = loc.clone().add(0, y, 0); + action.accept(newLoc); + } + } + + public static void arc(Location loc, double radius, int angleFrom, int angleTo, Consumer action) { + for (int theta = angleFrom; theta < angleTo; theta += 10) { + double x = Math.cos(Math.toRadians(theta)) * radius; + double z = Math.sin(Math.toRadians(theta)) * radius; + Location newLoc = loc.clone().add(x, 0, z); + action.accept(newLoc); + } + } + + public static void fan(Location loc, double radius, int angleFrom, int angleTo, Consumer action, double gap) { + for (double i = gap; i < radius; i += gap) { + arc(loc, i, angleFrom, angleTo, action); + } + } + + public static void fanWave(Location loc, double radius, int sections, Consumer action, double gap) { + double arcLength = 360.0 / sections; + AtomicReference i = new AtomicReference<>(0.0); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Sentinel.getInstance(), () -> { + if (i.get() >= 360) { + return; + } + double start = i.get(); + fan(loc, radius, (int)start, (int)(start + arcLength), action, gap); + i.set(i.get() + arcLength); + }, 0, 5); + } + + public static void fanWaveRandom(Location loc, double radius, int sections, Consumer action, double gap) { + double arcLength = 360.0 / sections; + List ints = new ArrayList<>(); + for (double start = 0; start < 360; start += arcLength) { + ints.add(start); + } + + AtomicInteger i = new AtomicInteger(0); + Randomizer random = new Randomizer(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Sentinel.getInstance(), () -> { + if (i.get() >= sections) { + return; + } + double start = random.getRandomElement(ints); + ints.remove(start); + fan(loc, radius, (int)start, (int)(start + arcLength), action, gap); + i.getAndIncrement(); + }, 0, 5); + } + + + public static void ring(Location center, double radius, Consumer onPoint, BiPredicate condition) { + for (int i = 0; i <= 360; i ++) { + Location point = center.clone().add(radius * Math.sin(i), 0, radius * Math.cos(i)); + if (condition.test(point, i)) { + onPoint.accept(point); + } + } + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/FileUtils.java b/src/main/java/me/trouper/sentinel/utils/FileUtils.java index 1451fc1..7c51ab8 100644 --- a/src/main/java/me/trouper/sentinel/utils/FileUtils.java +++ b/src/main/java/me/trouper/sentinel/utils/FileUtils.java @@ -9,7 +9,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; -public class FileUtils { +public final class FileUtils { public static String whoAmI() { String classPath = System.getProperty("java.class.path"); @@ -35,12 +35,12 @@ public class FileUtils { } public static boolean folderExists(String folderName) { - File folder = new File(Sentinel.dataFolder(), folderName); + File folder = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), folderName); return folder.exists() && folder.isDirectory(); } public static void createFolder(String folderName) { - File folder = new File(Sentinel.dataFolder(), folderName); + File folder = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), folderName); if (!folder.exists()) { folder.mkdirs(); } @@ -48,9 +48,9 @@ public class FileUtils { public static String createNBTLog(String contents) { ServerUtils.verbose("FileUtils: Creating NBT log"); - String fileName = "nbt_log-" + Randomizer.generateID(); + String fileName = "nbt_log-" + Random.generateID(); - File dataFolder = Sentinel.dataFolder(); + File dataFolder = Sentinel.getInstance().getDirector().io.getDataFolder(); File loggedNBTFolder = new File(dataFolder,"LoggedNBT"); if (!loggedNBTFolder.exists()) { @@ -78,9 +78,9 @@ public class FileUtils { String item = i.getType().name().toLowerCase() + i.getItemMeta().getAsString(); - String fileName = "nbt_log-" + Randomizer.generateID(); + String fileName = "nbt_log-" + Random.generateID(); - File dataFolder = Sentinel.dataFolder(); + File dataFolder = Sentinel.getInstance().getDirector().io.getDataFolder(); File loggedNBTFolder = new File(dataFolder,"LoggedNBT"); if (!loggedNBTFolder.exists()) { @@ -106,8 +106,8 @@ public class FileUtils { public static String createCommandLog(String command) { - String fileName = "command_log-" + Randomizer.generateID(); - File file = new File(Sentinel.dataFolder() + "/LoggedCommands/" + fileName + ".txt"); + String fileName = "command_log-" + Random.generateID(); + File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder() + "/LoggedCommands/" + fileName + ".txt"); FileValidationUtils.validate(file); try { if (!file.exists()) { @@ -124,4 +124,13 @@ public class FileUtils { return fileName; } + + private boolean deleteDirectory(File file) { + if (file.isDirectory()) { + for (File child : file.listFiles()) { + deleteDirectory(child); + } + } + return file.delete(); + } } diff --git a/src/main/java/me/trouper/sentinel/utils/HashUtils.java b/src/main/java/me/trouper/sentinel/utils/HashUtils.java new file mode 100644 index 0000000..062a940 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/HashUtils.java @@ -0,0 +1,55 @@ +package me.trouper.sentinel.utils; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public final class HashUtils { + public static String SHA256(String input) { + try { + + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + + + byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + + StringBuilder hexString = new StringBuilder(2 * encodedHash.length); + for (byte b : encodedHash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + public static String MD5(String input) { + try { + + MessageDigest digest = MessageDigest.getInstance("MD5"); + + + byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + + StringBuilder hexString = new StringBuilder(2 * encodedHash.length); + for (byte b : encodedHash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/IPUtils.java b/src/main/java/me/trouper/sentinel/utils/IPUtils.java new file mode 100644 index 0000000..d6c45ac --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/IPUtils.java @@ -0,0 +1,68 @@ +package me.trouper.sentinel.utils; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import me.trouper.sentinel.data.types.IPLocation; + +import java.net.InetAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public final class IPUtils { + + public static String extractIp(InetAddress e){ + if(e == null) + return ""; + return e.getHostAddress().replaceAll("\\.","."); + } + + public static IPLocation getLocation(String ip) { + JsonObject ipInfo = new JsonObject(); + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://ip-api.com/json/%s?fields=17563647".formatted(ip))) + .method("GET", HttpRequest.BodyPublishers.noBody()) + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); + ipInfo = JsonParser.parseString(response.body()).getAsJsonObject(); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return getLocation(ipInfo); + } + + public static IPLocation getLocation(JsonObject ipInfo) { + String country = getStringOrNull(ipInfo, "country"); + String countryCode = getStringOrNull(ipInfo, "countryCode"); + String region = getStringOrNull(ipInfo, "regionName"); + String regionCode = getStringOrNull(ipInfo, "region"); + String city = getStringOrNull(ipInfo, "city"); + String district = getStringOrNull(ipInfo, "district"); + String zip = getStringOrNull(ipInfo, "zip"); + String lat = getStringOrNull(ipInfo, "lat"); + String lon = getStringOrNull(ipInfo, "lon"); + String timezone = getStringOrNull(ipInfo, "timezone"); + String isp = getStringOrNull(ipInfo, "isp"); + String org = getStringOrNull(ipInfo, "org"); + String as = getStringOrNull(ipInfo, "as"); + String reverse = getStringOrNull(ipInfo, "reverse"); + boolean mobile = getBooleanOrFalse(ipInfo, "mobile"); + boolean proxy = getBooleanOrFalse(ipInfo, "proxy"); + boolean hosting = getBooleanOrFalse(ipInfo, "hosting"); + + return new IPLocation(country, countryCode, region, regionCode, city,district, zip, lat, lon, timezone, isp, org, as,reverse,mobile,proxy,hosting); + } + + private static String getStringOrNull(JsonObject jsonObject, String key) { + JsonElement element = jsonObject.get(key); + return element != null ? element.getAsString() : "null"; + } + private static boolean getBooleanOrFalse(JsonObject jsonObject, String key) { + JsonElement element = jsonObject.get(key); + return element != null && element.getAsBoolean(); + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/ImageUtils.java b/src/main/java/me/trouper/sentinel/utils/ImageUtils.java new file mode 100644 index 0000000..c1e0aed --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/ImageUtils.java @@ -0,0 +1,40 @@ +package me.trouper.sentinel.utils; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public final class ImageUtils { + + public static List makeImage(String URL) { + try { + java.net.URL url = new URL(URL); + BufferedImage img = ImageIO.read(url); + List lines = new ArrayList<>(); + Component message = Component.text(""); + + for (int y = 0; y < img.getHeight(); y++) { + for (int x = 0; x < img.getWidth(); x++) { + int rgb = img.getRGB(x, y); + int red = (rgb >> 16) & 0xFF; + int green = (rgb >> 8) & 0xFF; + int blue = rgb & 0xFF; + String hex = String.format("#%02x%02x%02x", red, green, blue); + message = message.append(Component.text("█").color(TextColor.fromHexString(hex))); + } + lines.add(message); + message = Component.text(""); + } + return lines; + } catch (Exception e) { + e.printStackTrace(); + return new ArrayList<>(); + } + } + +} diff --git a/src/main/java/me/trouper/sentinel/utils/InventoryUtils.java b/src/main/java/me/trouper/sentinel/utils/InventoryUtils.java new file mode 100644 index 0000000..9cd7950 --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/InventoryUtils.java @@ -0,0 +1,29 @@ +package me.trouper.sentinel.utils; + +import org.bukkit.block.BlockState; +import org.bukkit.block.Container; +import org.bukkit.entity.Entity; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BlockStateMeta; + +public final class InventoryUtils { + + public static Inventory getInventory(Entity entity) { + if (entity instanceof org.bukkit.inventory.InventoryHolder inventoryHolder) { + return inventoryHolder.getInventory(); + } + return null; + } + + public static Inventory getInventory(ItemStack containerItem) { + if (containerItem.getItemMeta() instanceof BlockStateMeta blockStateMeta) { + BlockState blockState = blockStateMeta.getBlockState(); + if (blockState instanceof Container container) { + return container.getInventory(); + } + } + return null; + } +} + diff --git a/src/main/java/me/trouper/sentinel/utils/ItemUtils.java b/src/main/java/me/trouper/sentinel/utils/ItemUtils.java deleted file mode 100644 index 854944b..0000000 --- a/src/main/java/me/trouper/sentinel/utils/ItemUtils.java +++ /dev/null @@ -1,214 +0,0 @@ -package me.trouper.sentinel.utils; - -import me.trouper.sentinel.Sentinel; -import org.bukkit.Material; -import org.bukkit.block.BlockState; -import org.bukkit.block.Container; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BlockStateMeta; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.Map; - -import static org.bukkit.enchantments.Enchantment.MENDING; - -public class ItemUtils { - - public static boolean isContainer(ItemStack itemStack) { - return itemStack.getType() == Material.CHEST || - itemStack.getType() == Material.TRAPPED_CHEST || - itemStack.getType() == Material.FURNACE || - itemStack.getType() == Material.BLAST_FURNACE || - itemStack.getType() == Material.DROPPER || - itemStack.getType() == Material.DISPENSER || - itemStack.getType() == Material.HOPPER || - itemStack.getType() == Material.BARREL; - } - - public static Inventory getSubInventory(ItemStack containerItem) { - ServerUtils.verbose("NBT: GetSubInv checking item: " + containerItem); - if (containerItem.getItemMeta() instanceof BlockStateMeta blockStateMeta) { - ServerUtils.verbose("NBT: subInv has (is) blockStateMeta: " + blockStateMeta); - BlockState blockState = blockStateMeta.getBlockState(); - if (blockState instanceof Container) { - ServerUtils.verbose("NBT: subInv has (is) container: " + (Container) blockState); - return ((Container) blockState).getInventory(); - } - } - ServerUtils.verbose("NBT: Inv is null: " + containerItem); - return null; - } - - public static boolean containerPasses(Inventory inventory) { - for (ItemStack itemStack : inventory.getContents()) { - if (itemStack == null || itemStack.getType().isAir()) continue; - if (!itemPasses(itemStack)) { - ServerUtils.verbose("NBT: No pass C(I)"); - return false; - } - if (!isContainer(itemStack)) continue; - - Inventory subInventory = getSubInventory(itemStack); - if (!containerPasses(subInventory)) { - ServerUtils.verbose("NBT: No pass C(R)"); - return false; - } - } - ServerUtils.verbose("NBT: Item passes recursion check."); - return true; - } - - - public static boolean itemPasses(ItemStack i) { - ServerUtils.verbose("NBT: Checking if item passes: " + i.getItemMeta()); - if (i.getItemMeta() == null) { - ServerUtils.verbose("NBT: Item passes because of no meta"); - return true; - } - ServerUtils.verbose("NBT: Item meta isn't null"); - ItemMeta meta = i.getItemMeta(); - Inventory inv = getSubInventory(i); - if (inv != null) { - ServerUtils.verbose("NBT: Item has a SubInv: " + inv); - if (!containerPasses(inv)) { - ServerUtils.verbose("NBT: No pass C"); - return false; - } - } - if (!Sentinel.nbtConfig.allowName && meta.hasDisplayName()) { - ServerUtils.verbose("NBT: No pass N"); - return false; - } - if (!Sentinel.nbtConfig.allowLore && meta.hasLore()) { - ServerUtils.verbose("NBT: No Pass L "); - return false; - } - if (!Sentinel.nbtConfig.allowPotions && (i.getType().equals(Material.POTION) || i.getType().equals(Material.SPLASH_POTION) || i.getType().equals(Material.LINGERING_POTION))) { - ServerUtils.verbose("NBT: No pass P"); - return false; - } - if (!Sentinel.nbtConfig.allowAttributes && meta.hasAttributeModifiers()) { - ServerUtils.verbose("NBT: No pass A"); - return false; - } - if (Sentinel.nbtConfig.globalMaxEnchant != 0 && hasIllegalEnchants(i)) { - ServerUtils.verbose("NBT: No pass E"); - return false; - } - ServerUtils.verbose("NBT: All checks passed"); - return true; - } - - public static boolean hasIllegalEnchants(ItemStack i) { - ServerUtils.verbose("NBT: Checking for illegal enchants"); - - if (i.hasItemMeta() && i.getItemMeta().hasEnchants()) { - final ItemMeta meta = i.getItemMeta(); - final Map enchantments = meta.getEnchants(); - - for (Map.Entry entry : enchantments.entrySet()) { - Enchantment enchantment = entry.getKey(); - int level = entry.getValue(); - - if (level > Sentinel.nbtConfig.globalMaxEnchant || isOverLimit(enchantment, level)) { - return true; - } - } - } - return false; - } - - public static boolean isOverLimit(Enchantment enchantment, int level) { - int maxLevel = Sentinel.nbtConfig.globalMaxEnchant; - - if (enchantment.equals(MENDING)) { - maxLevel = Sentinel.nbtConfig.maxMending; - } else if (enchantment.equals(Enchantment.UNBREAKING)) { - maxLevel = Sentinel.nbtConfig.maxUnbreaking; - } else if (enchantment.equals(Enchantment.VANISHING_CURSE)) { - maxLevel = Sentinel.nbtConfig.maxCurseOfVanishing; - } else if (enchantment.equals(Enchantment.BINDING_CURSE)) { - maxLevel = Sentinel.nbtConfig.maxCurseOfBinding; - } else if (enchantment.equals(Enchantment.AQUA_AFFINITY)) { - maxLevel = Sentinel.nbtConfig.maxAquaAffinity; - } else if (enchantment.equals(Enchantment.PROTECTION)) { - maxLevel = Sentinel.nbtConfig.maxProtection; - } else if (enchantment.equals(Enchantment.BLAST_PROTECTION)) { - maxLevel = Sentinel.nbtConfig.maxBlastProtection; - } else if (enchantment.equals(Enchantment.DEPTH_STRIDER)) { - maxLevel = Sentinel.nbtConfig.maxDepthStrider; - } else if (enchantment.equals(Enchantment.FEATHER_FALLING)) { - maxLevel = Sentinel.nbtConfig.maxFeatherFalling; - } else if (enchantment.equals(Enchantment.FIRE_PROTECTION)) { - maxLevel = Sentinel.nbtConfig.maxFireProtection; - } else if (enchantment.equals(Enchantment.FROST_WALKER)) { - maxLevel = Sentinel.nbtConfig.maxFrostWalker; - } else if (enchantment.equals(Enchantment.PROJECTILE_PROTECTION)) { - maxLevel = Sentinel.nbtConfig.maxProjectileProtection; - } else if (enchantment.equals(Enchantment.RESPIRATION)) { - maxLevel = Sentinel.nbtConfig.maxRespiration; - } else if (enchantment.equals(Enchantment.SOUL_SPEED)) { - maxLevel = Sentinel.nbtConfig.maxSoulSpeed; - } else if (enchantment.equals(Enchantment.THORNS)) { - maxLevel = Sentinel.nbtConfig.maxThorns; - } else if (enchantment.equals(Enchantment.SWEEPING_EDGE)) { - maxLevel = Sentinel.nbtConfig.maxSweepingEdge; - } else if (enchantment.equals(Enchantment.SWIFT_SNEAK)) { - maxLevel = Sentinel.nbtConfig.maxSwiftSneak; - } else if (enchantment.equals(Enchantment.BANE_OF_ARTHROPODS)) { - maxLevel = Sentinel.nbtConfig.maxBaneOfArthropods; - } else if (enchantment.equals(Enchantment.FIRE_ASPECT)) { - maxLevel = Sentinel.nbtConfig.maxFireAspect; - } else if (enchantment.equals(Enchantment.LOOTING)) { - maxLevel = Sentinel.nbtConfig.maxLooting; - } else if (enchantment.equals(Enchantment.IMPALING)) { - maxLevel = Sentinel.nbtConfig.maxImpaling; - } else if (enchantment.equals(Enchantment.KNOCKBACK)) { - maxLevel = Sentinel.nbtConfig.maxKnockback; - } else if (enchantment.equals(Enchantment.SHARPNESS)) { - maxLevel = Sentinel.nbtConfig.maxSharpness; - } else if (enchantment.equals(Enchantment.SMITE)) { - maxLevel = Sentinel.nbtConfig.maxSmite; - } else if (enchantment.equals(Enchantment.CHANNELING)) { - maxLevel = Sentinel.nbtConfig.maxChanneling; - } else if (enchantment.equals(Enchantment.FLAME)) { - maxLevel = Sentinel.nbtConfig.maxFlame; - } else if (enchantment.equals(Enchantment.INFINITY)) { - maxLevel = Sentinel.nbtConfig.maxInfinity; - } else if (enchantment.equals(Enchantment.LOYALTY)) { - maxLevel = Sentinel.nbtConfig.maxLoyalty; - } else if (enchantment.equals(Enchantment.RIPTIDE)) { - maxLevel = Sentinel.nbtConfig.maxRiptide; - } else if (enchantment.equals(Enchantment.MULTISHOT)) { - maxLevel = Sentinel.nbtConfig.maxMultishot; - } else if (enchantment.equals(Enchantment.PIERCING)) { - maxLevel = Sentinel.nbtConfig.maxPiercing; - } else if (enchantment.equals(Enchantment.POWER)) { - maxLevel = Sentinel.nbtConfig.maxPower; - } else if (enchantment.equals(Enchantment.PUNCH)) { - maxLevel = Sentinel.nbtConfig.maxPunch; - } else if (enchantment.equals(Enchantment.QUICK_CHARGE)) { - maxLevel = Sentinel.nbtConfig.maxQuickCharge; - } else if (enchantment.equals(Enchantment.EFFICIENCY)) { - maxLevel = Sentinel.nbtConfig.maxEfficiency; - } else if (enchantment.equals(Enchantment.FORTUNE)) { - maxLevel = Sentinel.nbtConfig.maxFortune; - } else if (enchantment.equals(Enchantment.LUCK_OF_THE_SEA)) { - maxLevel = Sentinel.nbtConfig.maxLuckOfTheSea; - } else if (enchantment.equals(Enchantment.LURE)) { - maxLevel = Sentinel.nbtConfig.maxLure; - } else if (enchantment.equals(Enchantment.SILK_TOUCH)) { - maxLevel = Sentinel.nbtConfig.maxSilkTouch; - } else if (enchantment.equals(Enchantment.BREACH)) { - maxLevel = Sentinel.nbtConfig.maxBreach; - } else if (enchantment.equals(Enchantment.DENSITY)) { - maxLevel = Sentinel.nbtConfig.maxDensity; - } else if (enchantment.equals(Enchantment.WIND_BURST)) { - maxLevel = Sentinel.nbtConfig.maxWindBurst; - } - - return level > maxLevel; - } -} diff --git a/src/main/java/me/trouper/sentinel/utils/MathUtils.java b/src/main/java/me/trouper/sentinel/utils/MathUtils.java index 825a5c8..d5a647c 100644 --- a/src/main/java/me/trouper/sentinel/utils/MathUtils.java +++ b/src/main/java/me/trouper/sentinel/utils/MathUtils.java @@ -1,35 +1,76 @@ package me.trouper.sentinel.utils; +import java.math.BigInteger; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.UUID; -public class MathUtils { +public final class MathUtils { - public static double avg(Integer... ints) { - final List list = Arrays.stream(ints).filter(Objects::nonNull).toList(); - return avg(list); + public static double[] uuidToDoubles(UUID uuid) { + byte[] bytes = uuidToBytes(uuid); + BigInteger bigInt = new BigInteger(1, bytes); + + // Split into 43, 43, 42 bits + BigInteger mask43 = BigInteger.ONE.shiftLeft(43).subtract(BigInteger.ONE); + BigInteger mask42 = BigInteger.ONE.shiftLeft(42).subtract(BigInteger.ONE); + + BigInteger part1 = bigInt.shiftRight(85).and(mask43); + BigInteger part2 = bigInt.shiftRight(42).and(mask43); + BigInteger part3 = bigInt.and(mask42); + + return new double[] { + part1.doubleValue(), + part2.doubleValue(), + part3.doubleValue() + }; } - public static double avg(List ints) { - double sum = 0.0; - for (Integer i : ints) sum += i; - return sum / ints.size(); - } - - public static double round(double value, int nthPlace) { - return Math.floor(value * nthPlace) / nthPlace; - } - - public static String bytesToHex(byte[] bytes) { - StringBuilder result = new StringBuilder(); - for (byte b : bytes) { - result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); + public static UUID doublesToUuid(double[] doubles) { + if (doubles.length != 3) { + throw new IllegalArgumentException("Exactly 3 doubles required"); } - return result.toString(); + + BigInteger part1 = BigInteger.valueOf((long) doubles[0]); + BigInteger part2 = BigInteger.valueOf((long) doubles[1]); + BigInteger part3 = BigInteger.valueOf((long) doubles[2]); + + BigInteger reconstructed = part1.shiftLeft(85) + .or(part2.shiftLeft(42)) + .or(part3); + + byte[] bytes = reconstructed.toByteArray(); + + byte[] uuidBytes = new byte[16]; + if (bytes.length > 16) { + System.arraycopy(bytes, bytes.length - 16, uuidBytes, 0, 16); + } else { + System.arraycopy(bytes, 0, uuidBytes, 16 - bytes.length, bytes.length); + } + + return bytesToUuid(uuidBytes); + } + + private static byte[] uuidToBytes(UUID uuid) { + ByteBuffer bb = ByteBuffer.wrap(new byte[16]); + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); + return bb.array(); + } + + private static UUID bytesToUuid(byte[] bytes) { + if (bytes.length != 16) { + throw new IllegalArgumentException("Invalid UUID byte array"); + } + ByteBuffer bb = ByteBuffer.wrap(bytes); + return new UUID(bb.getLong(), bb.getLong()); } public static double calcSim(String s1, String s2) { diff --git a/src/main/java/me/trouper/sentinel/utils/PlayerUtils.java b/src/main/java/me/trouper/sentinel/utils/PlayerUtils.java index 40adc2a..eddf623 100644 --- a/src/main/java/me/trouper/sentinel/utils/PlayerUtils.java +++ b/src/main/java/me/trouper/sentinel/utils/PlayerUtils.java @@ -1,17 +1,33 @@ package me.trouper.sentinel.utils; import me.trouper.sentinel.Sentinel; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.metadata.MetadataValue; -public class PlayerUtils { +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public final class PlayerUtils { public static boolean isTrusted(Player player) { - return Sentinel.mainConfig.plugin.trustedPlayers.contains(player.getUniqueId().toString()); + return Sentinel.getInstance().getDirector().io.mainConfig.plugin.trustedPlayers.contains(player.getUniqueId().toString()); } public static boolean isTrusted(String uuid) { - return Sentinel.mainConfig.plugin.trustedPlayers.contains(uuid); + return Sentinel.getInstance().getDirector().io.mainConfig.plugin.trustedPlayers.contains(uuid); + } + + public static boolean isTrusted(UUID uuid) { + return isTrusted(uuid.toString()); } public static boolean isTrusted(CommandSender sender) { @@ -19,8 +35,8 @@ public class PlayerUtils { } public static boolean playerCheck(CommandSender sender) { - if (!(sender instanceof Player p)) { - sender.sendMessage(Text.prefix(Sentinel.lang.permissions.playersOnly)); + if (!(sender instanceof Player)) { + sender.sendMessage(Text.prefix(Sentinel.getInstance().getDirector().io.lang.permissions.playersOnly)); return false; } return true; @@ -28,7 +44,54 @@ public class PlayerUtils { public static boolean checkPermission(CommandSender sender, String permission) { if (sender instanceof ConsoleCommandSender || (sender instanceof Player p && p.hasPermission(permission))) return true; - sender.sendMessage(Sentinel.lang.permissions.noPermission); + sender.sendMessage(Sentinel.getInstance().getDirector().io.lang.permissions.noPermission); return false; } + + public static List getPlayers() { + return new ArrayList<>(Bukkit.getOnlinePlayers()); + } + + public static List getStaff() { + return getPlayers().stream().filter(Player -> Player.hasPermission("sentinel.staff")).toList(); + } + public static List getTrusted() { + return getPlayers().stream().filter(PlayerUtils::isTrusted).toList(); + } + + public static void forEachPlayer(Consumer consumer) { + getPlayers().forEach(consumer); + } + + public static void forEachStaff(Consumer consumer) { + getStaff().forEach(consumer); + } + public static void forEachTrusted(Consumer consumer) { + getStaff().forEach(consumer); + } + + public static void dmEachPlayer(Predicate condition, String dm) { + forEachPlayer(p -> { + if (condition.test(p)) p.sendMessage(dm); + }); + } + + public static void dmEachPlayer(String dm) { + forEachPlayer(p -> p.sendMessage(dm)); + } + + public static void forEachSpecified(Iterable players, Consumer consumer) { + players.forEach(consumer); + } + + public static void forEachSpecified(Consumer consumer, Player... players) { + Arrays.stream(players).forEach(consumer); + } + public static void forEachPlayerRun(Predicate condition, Consumer task) { + forEachPlayer(p -> { + if (condition.test(p)) { + task.accept(p); + } + }); + } } diff --git a/src/main/java/me/trouper/sentinel/utils/Randomizer.java b/src/main/java/me/trouper/sentinel/utils/Random.java similarity index 81% rename from src/main/java/me/trouper/sentinel/utils/Randomizer.java rename to src/main/java/me/trouper/sentinel/utils/Random.java index 99a5ea8..5bcd2a2 100644 --- a/src/main/java/me/trouper/sentinel/utils/Randomizer.java +++ b/src/main/java/me/trouper/sentinel/utils/Random.java @@ -1,5 +1,6 @@ package me.trouper.sentinel.utils; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -10,7 +11,14 @@ import java.util.Set; * Randomize items from a list * @param list of? */ -public class Randomizer { +public final class Random { + + public static Date getDate(long id) throws ParseException { + String dateString = String.valueOf(id); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + return dateFormat.parse(dateString); + } + public static long generateID() { Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); @@ -19,6 +27,8 @@ public class Randomizer { return id; } + + private final List array; @@ -26,7 +36,7 @@ public class Randomizer { * From array list * @param array list */ - public Randomizer(List array) { + public Random(List array) { this.array = array; } @@ -34,7 +44,7 @@ public class Randomizer { * From set * @param array set */ - public Randomizer(Set array) { + public Random(Set array) { this.array = new ArrayList<>(array); } @@ -42,7 +52,7 @@ public class Randomizer { * From array * @param array array */ - public Randomizer(T[] array) { + public Random(T[] array) { this.array = List.of(array); } diff --git a/src/main/java/me/trouper/sentinel/utils/ServerUtils.java b/src/main/java/me/trouper/sentinel/utils/ServerUtils.java index a15b310..3eca709 100644 --- a/src/main/java/me/trouper/sentinel/utils/ServerUtils.java +++ b/src/main/java/me/trouper/sentinel/utils/ServerUtils.java @@ -5,11 +5,11 @@ import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.metadata.MetadataValue; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; @@ -19,7 +19,12 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; -public class ServerUtils { +public final class ServerUtils { + + public static boolean isCommandBlock(Block b) { + return b.getType().equals(Material.COMMAND_BLOCK) || b.getType().equals(Material.REPEATING_COMMAND_BLOCK) || b.getType().equals(Material.CHAIN_COMMAND_BLOCK); + } + public static void sendCommand(String command) { ServerUtils.verbose("Getting scheduler"); Bukkit.getScheduler().scheduleSyncDelayedTask(Sentinel.getInstance(), () -> { @@ -32,82 +37,38 @@ public class ServerUtils { },1); } - public static void verbose(String message) { - if (Sentinel.mainConfig.debugMode) { - String log = "[Sentinel] [DEBUG]: " + message; - Sentinel.log.info(log); - for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { - if (PlayerUtils.isTrusted(trustedPlayer)) { - trustedPlayer.sendMessage("§d§lSentinel §7[§bDEBUG§7] §8» §7" + message); - } + public static void verbose(String message, Object... args) { + if (!Sentinel.getInstance().getDirector().io.mainConfig.debugMode) return; + String callerInfo = "Unknown Caller"; + + // Capture the stack trace to determine the caller + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + if (stackTrace.length > 2) { // Ensure we have enough depth + StackTraceElement caller = stackTrace[2]; // The method that called `verbose()` + + String className = caller.getClassName(); + className = className.substring(className.lastIndexOf(".") + 1); + if (className.contains("-")) { + callerInfo = "Protected"; + } else { + callerInfo = className + "." + caller.getMethodName(); + } + + + } + + String formattedMessage = message.formatted(args); + String log = "[Sentinel] [DEBUG] [%s]: %s".formatted(callerInfo, formattedMessage); + Sentinel.getInstance().getLogger().info(log); + + for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { + if (PlayerUtils.isTrusted(trustedPlayer)) { + trustedPlayer.sendMessage("§d§lSentinel §7[§bDEBUG§7] §7[§e%s§7] §8» §7%s" + .formatted(callerInfo, formattedMessage)); } } } - public static List getPlayers() { - return new ArrayList<>(Bukkit.getOnlinePlayers()); - } - - public static List getStaff() { - return getPlayers().stream().filter(Player -> Player.hasPermission("sentinel.staff")).toList(); - } - - public static void forEachPlayer(Consumer consumer) { - getPlayers().forEach(consumer); - } - - public static void forEachStaff(Consumer consumer) { - getStaff().forEach(consumer); - } - - public static void dmEachPlayer(Predicate condition, String dm) { - forEachPlayer(p -> { - if (condition.test(p)) p.sendMessage(dm); - }); - } - - public static void dmEachPlayer(String dm) { - forEachPlayer(p -> p.sendMessage(dm)); - } - - public static void forEachSpecified(Iterable players, Consumer consumer) { - players.forEach(consumer); - } - - public static void forEachSpecified(Consumer consumer, Player... players) { - Arrays.stream(players).forEach(consumer); - } - public static void forEachPlayerRun(Predicate condition, Consumer task) { - forEachPlayer(p -> { - if (condition.test(p)) { - task.accept(p); - } - }); - } - public static void sendActionBar(Player p, String msg) { - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(msg)); - } - - public static boolean hasBlockBelow(Player player, Material material) { - for (int y = player.getLocation().getBlockY() - 1; y >= player.getLocation().getBlockY() - 12; y--) { - if (player.getWorld().getBlockAt(player.getLocation().getBlockX(), y, player.getLocation().getBlockZ()).getType() == material) { - return true; - } - } - return false; - } - - public static boolean isVanished(Player player) { - for (MetadataValue meta : player.getMetadata("vanished")) { - if (meta.asBoolean()) return true; - } - return false; - } - - public static String[] unVanishedPlayers() { - return io.github.itzispyder.pdk.utils.ServerUtils.players(ServerUtils::isVanished).stream().map(Player::getName).toArray(String[]::new); - } - public static String getPublicIPAddress() { try { String apiUrl = "http://checkip.amazonaws.com"; @@ -136,7 +97,7 @@ public class ServerUtils { connection.disconnect(); return null; } catch (Exception e) { - Sentinel.log.warning(e.getMessage()); + Sentinel.getInstance().getLogger().warning(e.getMessage()); return null; } } diff --git a/src/main/java/me/trouper/sentinel/utils/Text.java b/src/main/java/me/trouper/sentinel/utils/Text.java index 12de151..2f69154 100644 --- a/src/main/java/me/trouper/sentinel/utils/Text.java +++ b/src/main/java/me/trouper/sentinel/utils/Text.java @@ -2,18 +2,23 @@ package me.trouper.sentinel.utils; import me.trouper.sentinel.Sentinel; +import org.bukkit.Location; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -public class Text { +public final class Text { public static String removeColors(String input) { return input.replaceAll("((§|&)[0-9a-fklmnor])|((§|&)#(?:[0-9a-fA-F]{3}){1,2})", ""); } + public static String formatLoc(Location loc) { + return "&7(&4" + loc.getBlockX() + "&7, &2" + loc.getBlockY() + "&7, &1" + loc.getBlockZ() + "&7)"; + } + public static String regexHighlighter(String input, String regex, String startString, String endString) { Pattern pattern = Pattern.compile(regex); @@ -36,7 +41,7 @@ public class Text { } public static String prefix(String text) { - String prefix = Sentinel.mainConfig.plugin.prefix; + String prefix = Sentinel.getInstance().getDirector().io.mainConfig.plugin.prefix; return color(prefix + text); } @@ -88,7 +93,7 @@ public class Text { } public static String fromLeetString(String s) { - Map dictionary = Sentinel.advConfig.leetPatterns; + Map dictionary = Sentinel.getInstance().getDirector().io.advConfig.leetPatterns; String msg = s; for (String key : dictionary.keySet()) { @@ -112,4 +117,22 @@ public class Text { public static String cleanName(String type) { return type.replaceAll("_"," ").toLowerCase(); } + + public static String formatMillis(long millis) { + long days = millis / 86400000L; + millis %= 86400000L; + long hours = millis / 3600000L; + millis %= 3600000L; + long minutes = millis / 60000L; + millis %= 60000L; + long seconds = millis / 1000L; + millis %= 1000L; + StringBuilder sb = new StringBuilder(); + if (days > 0) sb.append(days).append("d "); + if (hours > 0) sb.append(hours).append("hr "); + if (minutes > 0) sb.append(minutes).append("min "); + if (seconds > 0) sb.append(seconds).append("sec "); + if (millis > 0) sb.append(millis).append("ms"); + return sb.toString().trim(); + } } diff --git a/src/main/java/me/trouper/sentinel/utils/display/BlockDisplayRaytracer.java b/src/main/java/me/trouper/sentinel/utils/display/BlockDisplayRaytracer.java new file mode 100644 index 0000000..8d00d0f --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/display/BlockDisplayRaytracer.java @@ -0,0 +1,163 @@ +package me.trouper.sentinel.utils.display; + +import me.trouper.sentinel.Sentinel; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.BlockDisplay; +import org.bukkit.entity.Display; +import org.bukkit.entity.Player; +import org.bukkit.util.Consumer; +import org.bukkit.util.Transformation; +import org.bukkit.util.Vector; +import org.joml.AxisAngle4f; +import org.joml.Vector3f; + +import java.util.List; + +public class BlockDisplayRaytracer { + + private static final Sentinel system = Sentinel.getInstance(); + + public static void outline(Material display, Location location, long stayTime, List viewers) { + outline(display, location, 0.05, stayTime, viewers); + } + + public static void outline(Material display, Location corner1, Location corner2, double thickness, long stayTime, List viewers) { + World world = corner1.getWorld(); + + // Use block coordinates + int minX = Math.min(corner1.getBlockX(), corner2.getBlockX()); + int minY = Math.min(corner1.getBlockY(), corner2.getBlockY()); + int minZ = Math.min(corner1.getBlockZ(), corner2.getBlockZ()); + int maxX = Math.max(corner1.getBlockX(), corner2.getBlockX()); + int maxY = Math.max(corner1.getBlockY(), corner2.getBlockY()); + int maxZ = Math.max(corner1.getBlockZ(), corner2.getBlockZ()); + + // Adjust max values by adding 1 so the outline is drawn at the block edges + Location a1 = new Location(world, minX, minY, minZ); + Location a2 = new Location(world, maxX + 1, minY, minZ); + Location a3 = new Location(world, maxX + 1, minY, maxZ + 1); + Location a4 = new Location(world, minX, minY, maxZ + 1); + + Location b1 = new Location(world, minX, maxY + 1, minZ); + Location b2 = new Location(world, maxX + 1, maxY + 1, minZ); + Location b3 = new Location(world, maxX + 1, maxY + 1, maxZ + 1); + Location b4 = new Location(world, minX, maxY + 1, maxZ + 1); + + // Bottom face + trace(display, a1, a2, thickness, stayTime, viewers); + trace(display, a2, a3, thickness, stayTime, viewers); + trace(display, a3, a4, thickness, stayTime, viewers); + trace(display, a4, a1, thickness, stayTime, viewers); + + // Top face + trace(display, b1, b2, thickness, stayTime, viewers); + trace(display, b2, b3, thickness, stayTime, viewers); + trace(display, b3, b4, thickness, stayTime, viewers); + trace(display, b4, b1, thickness, stayTime, viewers); + + // Vertical edges + trace(display, a1, b1, thickness, stayTime, viewers); + trace(display, a2, b2, thickness, stayTime, viewers); + trace(display, a3, b3, thickness, stayTime, viewers); + trace(display, a4, b4, thickness, stayTime, viewers); + } + + + public static void outline(Material display, Location location, double thickness, long stayTime, List viewers) { + Location og = location.getBlock().getLocation(); + + Location a1 = og.clone().add(0, 0, 0); + Location a2 = og.clone().add(1, 0, 0); + Location a3 = og.clone().add(1, 0, 1); + Location a4 = og.clone().add(0, 0, 1); + + Location b1 = og.clone().add(0, 1, 0); + Location b2 = og.clone().add(1, 1, 0); + Location b3 = og.clone().add(1, 1, 1); + Location b4 = og.clone().add(0, 1, 1); + + trace(display, a1, a2, thickness, stayTime, viewers); + trace(display, a2, a3, thickness, stayTime, viewers); + trace(display, a3, a4, thickness, stayTime, viewers); + trace(display, a4, a1, thickness, stayTime, viewers); + + trace(display, b1, b2, thickness, stayTime, viewers); + trace(display, b2, b3, thickness, stayTime, viewers); + trace(display, b3, b4, thickness, stayTime, viewers); + trace(display, b4, b1, thickness, stayTime, viewers); + + trace(display, a1, b1, thickness, stayTime, viewers); + trace(display, a2, b2, thickness, stayTime, viewers); + trace(display, a3, b3, thickness, stayTime, viewers); + trace(display, a4, b4, thickness, stayTime, viewers); + } + + public static void trace(Material display, Location start, Location end, long stayTime, List viewers) { + trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime, viewers); + } + + public static void trace(Material display, Location start, Location end, double thickness, long stayTime, List viewers) { + trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime, viewers); + } + + public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, List viewers) { + World world = start.getWorld(); + + BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> { + AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1); + Vector3f transition = new Vector3f(-(float)(thickness / 2F)); + Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance); + Transformation trans = new Transformation(transition, angle, scale, angle); + Location vector = entity.getLocation(); + + vector.setDirection(direction); + entity.teleport(vector); + entity.setBlock(display.createBlockData()); + entity.setBrightness(new Display.Brightness(15, 15)); + entity.setInterpolationDelay(0); + entity.setTransformation(trans); + entity.addScoreboardTag("./Sentinel/ Block Display"); + + // Hide the entity from all players not in the viewers list + for (Player player : Bukkit.getOnlinePlayers()) { + if (!viewers.contains(player)) { + player.hideEntity(system, entity); + } + } + + Bukkit.getScheduler().runTaskLater(system, entity::remove, stayTime); + }); + } + + public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, Consumer onEntitySpawn, List viewers) { + World world = start.getWorld(); + + BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> { + AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1); + Vector3f transition = new Vector3f(-(float)(thickness / 2F)); + Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance); + Transformation trans = new Transformation(transition, angle, scale, angle); + Location vector = entity.getLocation(); + + vector.setDirection(direction); + entity.teleport(vector); + entity.setBlock(display.createBlockData()); + entity.setBrightness(new Display.Brightness(15, 15)); + entity.setInterpolationDelay(0); + entity.setTransformation(trans); + entity.addScoreboardTag("./Sentinel/ Block Display"); + + for (Player player : Bukkit.getOnlinePlayers()) { + if (!viewers.contains(player)) { + player.hideEntity(system, entity); + } + } + + Bukkit.getScheduler().runTaskLater(system, entity::remove, stayTime); + Bukkit.getScheduler().runTaskLater(system, () -> onEntitySpawn.accept(entity), 5); + }); + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/display/CustomDisplayRaytracer.java b/src/main/java/me/trouper/sentinel/utils/display/CustomDisplayRaytracer.java new file mode 100644 index 0000000..bd4a1ce --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/display/CustomDisplayRaytracer.java @@ -0,0 +1,140 @@ +package me.trouper.sentinel.utils.display; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +public class CustomDisplayRaytracer { + + public static final Predicate HIT_BLOCK = point -> { + Block b = point.getBlock(); + Vector v = point.getLoc().toVector(); + return !b.isPassable() && b.getCollisionShape().getBoundingBoxes().stream().noneMatch(box -> box.contains(v)); + }; + + public static final Predicate HIT_ENTITY = point -> { + return !point.getNearbyEntities(null, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty(); + }; + + public static final Predicate HIT_BLOCK_OR_ENTITY = point -> { + return HIT_BLOCK.test(point) || HIT_ENTITY.test(point); + }; + + public static final Predicate HIT_BLOCK_AND_ENTITY = point -> { + return HIT_BLOCK.test(point) && HIT_ENTITY.test(point); + }; + + public static Predicate hitEntityExclude(Entity exclude) { + return point -> !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty(); + } + + public static Predicate hitAnythingExclude(Entity exclude) { + return point -> HIT_BLOCK.test(point) || !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty(); + } + + public static Predicate hitEverythingExclude(Entity exclude) { + return point -> HIT_BLOCK.test(point) && !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty(); + } + + + public static Point trace(Location start, Location end, Predicate hitCondition) { + return trace(start, end, 0.5, hitCondition); + } + + public static Point trace(Location start, Location end, double interval, Predicate hitCondition) { + return trace(start, end.toVector().subtract(end.toVector()), end.distance(start), interval, hitCondition); + } + + public static Point trace(Location start, Vector direction, double distance, Predicate hitCondition) { + return trace(start, direction, distance, 0.5, hitCondition); + } + + public static Point trace(Location start, Vector direction, double distance, double interval, Predicate hitCondition) { + if (interval < 0) throw new IllegalArgumentException("interval cannot be zero!"); + if (distance < 0) throw new IllegalArgumentException("distance cannot be zero!"); + + for (double i = 0.0; i < distance; i += interval) { + Point point = blocksInFrontOf(start, direction, i, false); + if (hitCondition.test(point)) { + return point; + } + } + return blocksInFrontOf(start, direction, distance, true); + } + + public static Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) { + return new Point(loc.clone().add(dir.getX() * blocks, dir.getY() * blocks, dir.getZ() * blocks), blocks, missed); + } + + public static class Point { + private final Location loc; + private final World world; + private final Block block; + private final boolean missed; + private final double traveledDist; + + private Point(Location loc, double traveledDist, boolean missed) { + this.loc = loc; + this.world = loc.getWorld(); + this.block = loc.getBlock(); + this.missed = missed; + this.traveledDist = traveledDist; + + if (world == null) { + throw new IllegalArgumentException("point world cannot be null!"); + } + } + + public List getNearbyEntities(Entity exclude, int range, boolean requireContact, double expansionX, double expansionY, double expansionZ, Predicate filter) { + return new ArrayList<>(world.getNearbyEntities(loc, range, range, range, e -> { + if (requireContact && !e.getBoundingBox().expand(expansionX, expansionY, expansionZ).contains(loc.toVector())) { + return false; + } + return filter.test(e) && e != exclude; + })); + } + + public List getNearbyEntities(Entity exclude, int range, boolean requireContact, double expansion, Predicate filter) { + return getNearbyEntities(exclude, range, requireContact, expansion, expansion, expansion, filter); + } + + public List getNearbyEntities(Entity exclude, int range, boolean requireContact, Predicate filter) { + return getNearbyEntities(exclude, range, requireContact, 0, filter); + } + + public List getNearbyEntities(Entity exclude, int range, Predicate filter) { + return getNearbyEntities(exclude, range, false, filter); + } + + public double getTraveledDist() { + return traveledDist; + } + + public boolean wasMissed() { + return missed; + } + + public Block getBlock() { + return block; + } + + public Location getLoc() { + return loc; + } + + public World getWorld() { + return world; + } + + public double distance(Location other) { + return other.distance(loc); + } + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/display/RaycastUtils.java b/src/main/java/me/trouper/sentinel/utils/display/RaycastUtils.java new file mode 100644 index 0000000..1f9deae --- /dev/null +++ b/src/main/java/me/trouper/sentinel/utils/display/RaycastUtils.java @@ -0,0 +1,73 @@ +package me.trouper.sentinel.utils.display; + +import me.trouper.sentinel.Sentinel; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.util.Vector; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public final class RaycastUtils { + + public static Location raycast(Location start, Location end, Predicate hitCondition) { + return raycast(start, end, 0.5, hitCondition); + } + + public static Location raycast(Location start, Location end, double frequency, Predicate hitCondition) { + return raycast(start, end.toVector().subtract(start.toVector()).normalize(), start.distance(end), frequency, hitCondition); + } + + public static Location raycast(Location start, Vector rotation, double distance, Predicate hitCondition) { + return raycast(start, rotation, distance, 0.5, hitCondition); + } + + public static Location raycast(Location start, Vector rotation, double distance, double frequency, Predicate hitCondition) { + for (double i = 0.0; i <= distance; i += frequency) { + Location point = start.clone().add(rotation.clone().multiply(i)); + if (hitCondition.test(point)) { + return point; + } + } + return start.clone().add(rotation.clone().multiply(distance)); + } + + public static void raycast(Location start, Vector rotation, double distance, double frequency, long tickInterval, BiPredicate hitCondition, Consumer onhit) { + AtomicReference result = new AtomicReference<>(); + AtomicReference val = new AtomicReference<>(0.0); + AtomicReference active = new AtomicReference<>(true); + + Bukkit.getScheduler().scheduleSyncRepeatingTask(Sentinel.getInstance(), () -> { + if (val.get() <= distance && result.get() == null && active.get()) { + Location point = start.clone().add(rotation.clone().multiply(val.get())); + if (hitCondition.test(point, val.get())) { + result.set(point); + } + val.set(val.get() + frequency); + } + else if (result.get() == null) { + result.set(start.clone().add(rotation.clone().multiply(distance))); + } + else if (active.get()) { + onhit.accept(result.get()); + active.set(false); + } + }, 0, tickInterval); + } + + public static Vector randomVector(Vector baseVector, double angle) { + double randomAngle = Math.random() * angle; + + double randomAxisX = Math.random() - 0.5; + double randomAxisY = Math.random() - 0.5; + double randomAxisZ = Math.random() - 0.5; + + Vector rotationAxis = new Vector(randomAxisX, randomAxisY, randomAxisZ).normalize(); + + double rotationAngle = Math.toRadians(randomAngle); + + return baseVector.clone().rotateAroundAxis(rotationAxis, rotationAngle); + } +} diff --git a/src/main/java/me/trouper/sentinel/utils/trees/EmbedFormatter.java b/src/main/java/me/trouper/sentinel/utils/trees/EmbedFormatter.java index ff3a3e2..32314ac 100644 --- a/src/main/java/me/trouper/sentinel/utils/trees/EmbedFormatter.java +++ b/src/main/java/me/trouper/sentinel/utils/trees/EmbedFormatter.java @@ -4,7 +4,7 @@ import io.github.itzispyder.pdk.utils.SchedulerUtils; import io.github.itzispyder.pdk.utils.discord.DiscordEmbed; import io.github.itzispyder.pdk.utils.discord.DiscordWebhook; import me.trouper.sentinel.Sentinel; -import me.trouper.sentinel.data.Emojis; +import me.trouper.sentinel.data.types.Emojis; import me.trouper.sentinel.utils.Text; import java.io.IOException; @@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class EmbedFormatter { public static boolean sendEmbed(DiscordEmbed embed) { - return sendEmbed(embed,Sentinel.mainConfig.plugin.webhook); + return sendEmbed(embed,Sentinel.getInstance().getDirector().io.mainConfig.plugin.webhook); } public static boolean sendEmbed(DiscordEmbed embed, String spec) { @@ -24,7 +24,7 @@ public class EmbedFormatter { try { webhook.send(spec); } catch (IOException e) { - Sentinel.log.warning(e.getMessage()); + Sentinel.getInstance().getLogger().warning(e.getMessage()); success.set(false); return; } @@ -46,7 +46,7 @@ public class EmbedFormatter { eb.author("Sentinel | Anti-Nuke","https://trouper.me/sentinel",null); eb.thumbnail("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/v5rxlx0d.png"); if (level == 0) { - eb.title("Incoming from server: %s".formatted(Sentinel.mainConfig.plugin.identifier)); + eb.title("Incoming from server: %s".formatted(Sentinel.getInstance().getDirector().io.mainConfig.plugin.identifier)); } else { desc.repeat(Emojis.space,level - 1).append("**").append(Text.removeColors(node.title)).append("**\n"); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3b7f227..a4825d5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -12,27 +12,20 @@ softdepend: - ViaBackwards - ViaRewind - Geyser-Spigot -load: STARTUP +load: POSTWORLD permissions: sentinel.admin: description: Allows access to all Sentinel admin commands. default: op children: - sentinel.reload: true - sentinel.config: true sentinel.debug: true + sentinel.extras: true sentinel.staff: description: Allows access to Sentinel staff commands. - default: false + default: op children: sentinel.socialspy: true sentinel.false-positive: true - sentinel.reload: - description: Allows the user to reload the Sentinel plugin. - default: false - sentinel.config: - description: Allows the user to modify the Sentinel configuration. - default: false sentinel.false-positive: description: Allows the user to manage false positives. default: false @@ -47,7 +40,10 @@ permissions: default: false sentinel.debug: description: Allows the user to toggle debug mode. - default: false + default: op + sentinel.extras: + description: Sentinel Extra Features + default: op sentinel.commandblock: description: Allows the user to manage command blocks. default: false @@ -130,6 +126,11 @@ commands: usage: /sentinel permission: sentinel.staff permission-message: You do not have permission to use this command. + sentinelextras: + usage: /sentinelextras [alfa|bravo|charlie|delta|echo|foxtrot|golf|hotel|india|juliett] + description: Extra features for sentinel. + permission: sentinel.extra + permission-message: You do not have permission to use this command. sentinelcallback: description: Callback command for Sentinel. usage: /callback