diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..85e7c1d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/.idea/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..b589d56
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..d8e9561
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..abc8b6a
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..c9139ed
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..92341c7
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5126b79
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..9a37280
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/Sentinel.main.iml b/.idea/modules/Sentinel.main.iml
new file mode 100644
index 0000000..746f1fd
--- /dev/null
+++ b/.idea/modules/Sentinel.main.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ PAPER
+ ADVENTURE
+
+ 1
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 662ca37..3362e80 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,12 +5,27 @@ plugins {
group = project.group
version = project.version
+jar {
+ from {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ configurations.runtimeClasspath.collect {
+ it.isDirectory() ? it : zipTree(it)
+ }
+ }
+}
+
repositories {
mavenCentral()
+ maven {
+ url "https://repo.dmulloy2.net/repository/public/"
+ }
maven {
name = 'spigotmc-repo'
url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
}
+ maven {
+ url = uri("https://repo.papermc.io/repository/maven-public/")
+ }
maven {
name = 'sonatype'
url = 'https://oss.sonatype.org/content/groups/public/'
@@ -18,15 +33,18 @@ repositories {
}
dependencies {
- compileOnly "org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT"
+ compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT'
+ compileOnly 'com.comphenix.protocol:ProtocolLib:5.1.0'
implementation 'com.google.code.gson:gson:2.10.1'
+ implementation files("libs/PDK-1.3.4.jar")
}
-def targetJavaVersion = 16
+def targetJavaVersion = 17
java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
+ toolchain.languageVersion.set(JavaLanguageVersion.of(17))
if (JavaVersion.current() < javaVersion) {
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
}
@@ -38,6 +56,13 @@ tasks.withType(JavaCompile).configureEach {
}
}
+tasks.register('copyDeps', Copy) {
+ from configurations.runtimeClasspath
+ into 'build/deps'
+ include '*.jar'
+}
+
+
processResources {
def props = [version: version]
inputs.properties props
@@ -52,4 +77,3 @@ compileJava.options.encoding("UTF-8")
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
-
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..bd40be1
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Navigate to the directory containing the Gradle project
+cd "/run/media/trouper/1TB drive/IJ/IdeaProjects/Sentinel/" || exit
+
+# Run the Gradle build command
+./gradlew build
+
+# Check if the build was successful
+if [ $? -ne 0 ]; then
+ echo "Gradle build failed"
+ exit 1
+fi
+
+# Specify the output file path (modify this according to your build configuration)
+OUTPUT_FILE_PATH="/run/media/trouper/1TB drive/IJ/IdeaProjects/Sentinel/build/libs/Sentinel-0.2.6.jar"
+
+# Check if the output file exists
+if [ ! -f "$OUTPUT_FILE_PATH" ]; then
+ echo "Output file not found: $OUTPUT_FILE_PATH"
+ exit 1
+fi
+
+# Upload the file to the SFTP server
+HOST="yessir.network"
+PORT="2022"
+USER="obvwolf.1f8509dc"
+PASSWORD='^8u%eQ2u6^TyuDU&$NNmW52s' # Enclose the password in single quotes if it has special characters
+REMOTE_DIR="/plugins/"
+
+# Use 'lftp' to handle the SFTP upload
+lftp -u "$USER","$PASSWORD" sftp://"$HOST":"$PORT" < "$TEMP_FILE"
+ echo "bye" >> "$TEMP_FILE"
+
+ # Use sftp non-interactively with the specified commands
+ sftp -oStrictHostKeyChecking=no -oBatchMode=no -b "$TEMP_FILE" "$SFTP_USER@$SFTP_HOST" <
+ connection-throttle: Connection throttled! Please wait before reconnecting.
+ flying-player:
+ flying-vehicle:
+ no-permission: I'm sorry, but you do not have permission to perform this command.
+ Please contact the server administrators if you believe that this is in error.
+ use-display-name-in-quit-message: false
+misc:
+ chat-threads:
+ chat-executor-core-size: -1
+ chat-executor-max-size: -1
+ compression-level: default
+ fix-entity-position-desync: true
+ load-permissions-yml-before-plugins: true
+ max-joins-per-tick: 5
+ region-file-cache-size: 256
+ strict-advancement-dimension-check: false
+ use-alternative-luck-formula: false
+ use-dimension-type-for-custom-spawners: false
+packet-limiter:
+ all-packets:
+ action: KICK
+ interval: 7.0
+ max-packet-rate: 500.0
+ kick-message:
+ overrides:
+ ServerboundPlaceRecipePacket:
+ action: DROP
+ interval: 4.0
+ max-packet-rate: 5.0
+player-auto-save:
+ max-per-tick: -1
+ rate: -1
+proxies:
+ bungee-cord:
+ online-mode: true
+ proxy-protocol: false
+ velocity:
+ enabled: false
+ online-mode: false
+ secret: ''
+scoreboards:
+ save-empty-scoreboard-teams: false
+ track-plugin-scoreboards: false
+spam-limiter:
+ incoming-packet-threshold: 300
+ recipe-spam-increment: 1
+ recipe-spam-limit: 20
+ tab-spam-increment: 1
+ tab-spam-limit: 500
+timings:
+ enabled: true
+ hidden-config-entries:
+ - database
+ - proxies.velocity.secret
+ history-interval: 300
+ history-length: 3600
+ server-name: Unknown Server
+ server-name-privacy: false
+ url: https://timings.aikar.co/
+ verbose: true
+unsupported-settings:
+ allow-grindstone-overstacking: false
+ allow-headless-pistons: false
+ allow-permanent-block-break-exploits: false
+ allow-piston-duplication: false
+ compression-format: ZLIB
+ perform-username-validation: true
+watchdog:
+ early-warning-delay: 10000
+ early-warning-every: 5000
diff --git a/server/config/paper-world-defaults.yml b/server/config/paper-world-defaults.yml
new file mode 100644
index 0000000..1594b27
--- /dev/null
+++ b/server/config/paper-world-defaults.yml
@@ -0,0 +1,307 @@
+# This is the world defaults configuration file for Paper.
+# As you can see, there's a lot to configure. Some options may impact gameplay, so use
+# with caution, and make sure you know what each option does before configuring.
+#
+# If you need help with the configuration or have any questions related to Paper,
+# join us in our Discord or check the docs page.
+#
+# Configuration options here apply to all worlds, unless you specify overrides inside
+# the world-specific config file inside each world folder.
+#
+# Docs: https://docs.papermc.io/
+# Discord: https://discord.gg/papermc
+# Website: https://papermc.io/
+
+_version: 30
+anticheat:
+ anti-xray:
+ enabled: false
+ engine-mode: 1
+ hidden-blocks:
+ - copper_ore
+ - deepslate_copper_ore
+ - raw_copper_block
+ - gold_ore
+ - deepslate_gold_ore
+ - iron_ore
+ - deepslate_iron_ore
+ - raw_iron_block
+ - coal_ore
+ - deepslate_coal_ore
+ - lapis_ore
+ - deepslate_lapis_ore
+ - mossy_cobblestone
+ - obsidian
+ - chest
+ - diamond_ore
+ - deepslate_diamond_ore
+ - redstone_ore
+ - deepslate_redstone_ore
+ - clay
+ - emerald_ore
+ - deepslate_emerald_ore
+ - ender_chest
+ lava-obscures: false
+ max-block-height: 64
+ replacement-blocks:
+ - stone
+ - oak_planks
+ - deepslate
+ update-radius: 2
+ use-permission: false
+ obfuscation:
+ items:
+ hide-durability: false
+ hide-itemmeta: false
+ hide-itemmeta-with-visual-effects: false
+chunks:
+ auto-save-interval: default
+ delay-chunk-unloads-by: 10s
+ entity-per-chunk-save-limit:
+ arrow: -1
+ ender_pearl: -1
+ experience_orb: -1
+ fireball: -1
+ small_fireball: -1
+ snowball: -1
+ fixed-chunk-inhabited-time: -1
+ flush-regions-on-save: false
+ max-auto-save-chunks-per-tick: 24
+ prevent-moving-into-unloaded-chunks: false
+collisions:
+ allow-player-cramming-damage: false
+ allow-vehicle-collisions: true
+ fix-climbing-bypassing-cramming-rule: false
+ max-entity-collisions: 8
+ only-players-collide: false
+command-blocks:
+ force-follow-perm-level: true
+ permissions-level: 2
+entities:
+ armor-stands:
+ do-collision-entity-lookups: true
+ tick: true
+ behavior:
+ allow-spider-world-border-climbing: true
+ baby-zombie-movement-modifier: 0.5
+ disable-chest-cat-detection: false
+ disable-creeper-lingering-effect: false
+ disable-player-crits: false
+ door-breaking-difficulty:
+ husk:
+ - HARD
+ vindicator:
+ - NORMAL
+ - HARD
+ zombie:
+ - HARD
+ zombie_villager:
+ - HARD
+ zombified_piglin:
+ - HARD
+ ender-dragons-death-always-places-dragon-egg: false
+ experience-merge-max-value: -1
+ mobs-can-always-pick-up-loot:
+ skeletons: false
+ zombies: false
+ nerf-pigmen-from-nether-portals: false
+ parrots-are-unaffected-by-player-movement: false
+ phantoms-do-not-spawn-on-creative-players: true
+ phantoms-only-attack-insomniacs: true
+ phantoms-spawn-attempt-max-seconds: 119
+ phantoms-spawn-attempt-min-seconds: 60
+ piglins-guard-chests: true
+ pillager-patrols:
+ disable: false
+ spawn-chance: 0.2
+ spawn-delay:
+ per-player: false
+ ticks: 12000
+ start:
+ day: 5
+ per-player: false
+ player-insomnia-start-ticks: 72000
+ should-remove-dragon: false
+ spawner-nerfed-mobs-should-jump: false
+ zombie-villager-infection-chance: default
+ zombies-target-turtle-eggs: true
+ entities-target-with-follow-range: false
+ markers:
+ tick: true
+ mob-effects:
+ immune-to-wither-effect:
+ wither: true
+ wither-skeleton: true
+ spiders-immune-to-poison-effect: true
+ undead-immune-to-certain-effects: true
+ sniffer:
+ boosted-hatch-time: default
+ hatch-time: default
+ spawning:
+ all-chunks-are-slime-chunks: false
+ alt-item-despawn-rate:
+ enabled: false
+ items:
+ cobblestone: 300
+ count-all-mobs-for-spawning: false
+ creative-arrow-despawn-rate: default
+ despawn-ranges:
+ ambient:
+ hard: 128
+ soft: 32
+ axolotls:
+ hard: 128
+ soft: 32
+ creature:
+ hard: 128
+ soft: 32
+ misc:
+ hard: 128
+ soft: 32
+ monster:
+ hard: 128
+ soft: 32
+ underground_water_creature:
+ hard: 128
+ soft: 32
+ water_ambient:
+ hard: 64
+ soft: 32
+ water_creature:
+ hard: 128
+ soft: 32
+ disable-mob-spawner-spawn-egg-transformation: false
+ duplicate-uuid:
+ mode: SAFE_REGEN
+ safe-regen-delete-range: 32
+ filter-bad-tile-entity-nbt-from-falling-blocks: true
+ filtered-entity-tag-nbt-paths:
+ - Pos
+ - Motion
+ - SleepingX
+ - SleepingY
+ - SleepingZ
+ iron-golems-can-spawn-in-air: false
+ monster-spawn-max-light-level: default
+ non-player-arrow-despawn-rate: default
+ per-player-mob-spawns: true
+ scan-for-legacy-ender-dragon: true
+ skeleton-horse-thunder-spawn-chance: default
+ slime-spawn-height:
+ slime-chunk:
+ maximum: 40.0
+ surface-biome:
+ maximum: 70.0
+ minimum: 50.0
+ spawn-limits:
+ ambient: -1
+ axolotls: -1
+ creature: -1
+ monster: -1
+ underground_water_creature: -1
+ water_ambient: -1
+ water_creature: -1
+ wandering-trader:
+ spawn-chance-failure-increment: 25
+ spawn-chance-max: 75
+ spawn-chance-min: 25
+ spawn-day-length: 24000
+ spawn-minute-length: 1200
+ wateranimal-spawn-height:
+ maximum: default
+ minimum: default
+ tracking-range-y:
+ animal: default
+ display: default
+ enabled: false
+ misc: default
+ monster: default
+ other: default
+ player: default
+environment:
+ disable-explosion-knockback: false
+ disable-ice-and-snow: false
+ disable-teleportation-suffocation-check: false
+ disable-thunder: false
+ fire-tick-delay: 30
+ frosted-ice:
+ delay:
+ max: 40
+ min: 20
+ enabled: true
+ generate-flat-bedrock: false
+ nether-ceiling-void-damage-height: disabled
+ optimize-explosions: false
+ portal-create-radius: 16
+ portal-search-radius: 128
+ portal-search-vanilla-dimension-scaling: true
+ treasure-maps:
+ enabled: true
+ find-already-discovered:
+ loot-tables: default
+ villager-trade: false
+ water-over-lava-flow-speed: 5
+feature-seeds:
+ generate-random-seeds-for-all: false
+fishing-time-range:
+ maximum: 600
+ minimum: 100
+fixes:
+ disable-unloaded-chunk-enderpearl-exploit: true
+ falling-block-height-nerf: disabled
+ fix-items-merging-through-walls: false
+ prevent-tnt-from-moving-in-water: false
+ split-overstacked-loot: true
+ tnt-entity-height-nerf: disabled
+hopper:
+ cooldown-when-full: true
+ disable-move-event: false
+ ignore-occluding-blocks: false
+lootables:
+ auto-replenish: false
+ max-refills: -1
+ refresh-max: 2d
+ refresh-min: 12h
+ reset-seed-on-fill: true
+ restrict-player-reloot: true
+ restrict-player-reloot-time: disabled
+maps:
+ item-frame-cursor-limit: 128
+ item-frame-cursor-update-interval: 10
+max-growth-height:
+ bamboo:
+ max: 16
+ min: 11
+ cactus: 3
+ reeds: 3
+misc:
+ disable-end-credits: false
+ disable-relative-projectile-velocity: false
+ disable-sprint-interruption-on-attack: false
+ light-queue-size: 20
+ max-leash-distance: 10.0
+ redstone-implementation: VANILLA
+ shield-blocking-delay: 5
+ show-sign-click-command-failure-msgs-to-player: false
+ update-pathfinding-on-block-update: true
+scoreboards:
+ allow-non-player-entities-on-scoreboards: true
+ use-vanilla-world-scoreboard-name-coloring: false
+spawn:
+ allow-using-signs-inside-spawn-protection: false
+ keep-spawn-loaded: true
+ keep-spawn-loaded-range: 10
+tick-rates:
+ behavior:
+ villager:
+ validatenearbypoi: -1
+ container-update: 1
+ dry-farmland: 1
+ grass-spread: 1
+ mob-spawner: 1
+ sensor:
+ villager:
+ secondarypoisensor: 40
+ wet-farmland: 1
+unsupported-settings:
+ fix-invulnerable-end-crystal-exploit: true
diff --git a/server/eula.txt b/server/eula.txt
new file mode 100644
index 0000000..ac74b96
--- /dev/null
+++ b/server/eula.txt
@@ -0,0 +1 @@
+eula=true
\ No newline at end of file
diff --git a/server/help.yml b/server/help.yml
new file mode 100644
index 0000000..e69de29
diff --git a/server/libraries/com/github/oshi/oshi-core/6.4.5/oshi-core-6.4.5.jar b/server/libraries/com/github/oshi/oshi-core/6.4.5/oshi-core-6.4.5.jar
new file mode 100644
index 0000000..ed5992e
Binary files /dev/null and b/server/libraries/com/github/oshi/oshi-core/6.4.5/oshi-core-6.4.5.jar differ
diff --git a/server/libraries/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar b/server/libraries/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar
new file mode 100644
index 0000000..59222d9
Binary files /dev/null and b/server/libraries/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar differ
diff --git a/server/libraries/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar b/server/libraries/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar
new file mode 100644
index 0000000..a88c5bd
Binary files /dev/null and b/server/libraries/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar differ
diff --git a/server/libraries/com/google/errorprone/error_prone_annotations/2.18.0/error_prone_annotations-2.18.0.jar b/server/libraries/com/google/errorprone/error_prone_annotations/2.18.0/error_prone_annotations-2.18.0.jar
new file mode 100644
index 0000000..e072fe0
Binary files /dev/null and b/server/libraries/com/google/errorprone/error_prone_annotations/2.18.0/error_prone_annotations-2.18.0.jar differ
diff --git a/server/libraries/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar b/server/libraries/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar
new file mode 100644
index 0000000..9b56dc7
Binary files /dev/null and b/server/libraries/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar differ
diff --git a/server/libraries/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar b/server/libraries/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar
new file mode 100644
index 0000000..e71fd46
Binary files /dev/null and b/server/libraries/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar differ
diff --git a/server/libraries/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar b/server/libraries/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
new file mode 100644
index 0000000..45832c0
Binary files /dev/null and b/server/libraries/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar differ
diff --git a/server/libraries/com/google/protobuf/protobuf-java/3.21.9/protobuf-java-3.21.9.jar b/server/libraries/com/google/protobuf/protobuf-java/3.21.9/protobuf-java-3.21.9.jar
new file mode 100644
index 0000000..c4fd860
Binary files /dev/null and b/server/libraries/com/google/protobuf/protobuf-java/3.21.9/protobuf-java-3.21.9.jar differ
diff --git a/server/libraries/com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar b/server/libraries/com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar
new file mode 100644
index 0000000..dfd5856
Binary files /dev/null and b/server/libraries/com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar differ
diff --git a/server/libraries/com/lmax/disruptor/3.4.4/disruptor-3.4.4.jar b/server/libraries/com/lmax/disruptor/3.4.4/disruptor-3.4.4.jar
new file mode 100644
index 0000000..8a918cf
Binary files /dev/null and b/server/libraries/com/lmax/disruptor/3.4.4/disruptor-3.4.4.jar differ
diff --git a/server/libraries/com/mojang/authlib/6.0.52/authlib-6.0.52.jar b/server/libraries/com/mojang/authlib/6.0.52/authlib-6.0.52.jar
new file mode 100644
index 0000000..c489f9d
Binary files /dev/null and b/server/libraries/com/mojang/authlib/6.0.52/authlib-6.0.52.jar differ
diff --git a/server/libraries/com/mojang/brigadier/1.2.9/brigadier-1.2.9.jar b/server/libraries/com/mojang/brigadier/1.2.9/brigadier-1.2.9.jar
new file mode 100644
index 0000000..ea2f234
Binary files /dev/null and b/server/libraries/com/mojang/brigadier/1.2.9/brigadier-1.2.9.jar differ
diff --git a/server/libraries/com/mojang/datafixerupper/6.0.8/datafixerupper-6.0.8.jar b/server/libraries/com/mojang/datafixerupper/6.0.8/datafixerupper-6.0.8.jar
new file mode 100644
index 0000000..2570a94
Binary files /dev/null and b/server/libraries/com/mojang/datafixerupper/6.0.8/datafixerupper-6.0.8.jar differ
diff --git a/server/libraries/com/mojang/logging/1.1.1/logging-1.1.1.jar b/server/libraries/com/mojang/logging/1.1.1/logging-1.1.1.jar
new file mode 100644
index 0000000..cf33dc5
Binary files /dev/null and b/server/libraries/com/mojang/logging/1.1.1/logging-1.1.1.jar differ
diff --git a/server/libraries/com/mysql/mysql-connector-j/8.2.0/mysql-connector-j-8.2.0.jar b/server/libraries/com/mysql/mysql-connector-j/8.2.0/mysql-connector-j-8.2.0.jar
new file mode 100644
index 0000000..96fae38
Binary files /dev/null and b/server/libraries/com/mysql/mysql-connector-j/8.2.0/mysql-connector-j-8.2.0.jar differ
diff --git a/server/libraries/com/velocitypowered/velocity-native/3.1.2-SNAPSHOT/velocity-native-3.1.2-SNAPSHOT.jar b/server/libraries/com/velocitypowered/velocity-native/3.1.2-SNAPSHOT/velocity-native-3.1.2-SNAPSHOT.jar
new file mode 100644
index 0000000..a072935
Binary files /dev/null and b/server/libraries/com/velocitypowered/velocity-native/3.1.2-SNAPSHOT/velocity-native-3.1.2-SNAPSHOT.jar differ
diff --git a/server/libraries/commons-codec/commons-codec/1.16.0/commons-codec-1.16.0.jar b/server/libraries/commons-codec/commons-codec/1.16.0/commons-codec-1.16.0.jar
new file mode 100644
index 0000000..854fc7e
Binary files /dev/null and b/server/libraries/commons-codec/commons-codec/1.16.0/commons-codec-1.16.0.jar differ
diff --git a/server/libraries/commons-io/commons-io/2.13.0/commons-io-2.13.0.jar b/server/libraries/commons-io/commons-io/2.13.0/commons-io-2.13.0.jar
new file mode 100644
index 0000000..eb316f4
Binary files /dev/null and b/server/libraries/commons-io/commons-io/2.13.0/commons-io-2.13.0.jar differ
diff --git a/server/libraries/commons-lang/commons-lang/2.6/commons-lang-2.6.jar b/server/libraries/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
new file mode 100644
index 0000000..98467d3
Binary files /dev/null and b/server/libraries/commons-lang/commons-lang/2.6/commons-lang-2.6.jar differ
diff --git a/server/libraries/io/leangen/geantyref/geantyref/1.3.15/geantyref-1.3.15.jar b/server/libraries/io/leangen/geantyref/geantyref/1.3.15/geantyref-1.3.15.jar
new file mode 100644
index 0000000..3d36fba
Binary files /dev/null and b/server/libraries/io/leangen/geantyref/geantyref/1.3.15/geantyref-1.3.15.jar differ
diff --git a/server/libraries/io/netty/netty-buffer/4.1.97.Final/netty-buffer-4.1.97.Final.jar b/server/libraries/io/netty/netty-buffer/4.1.97.Final/netty-buffer-4.1.97.Final.jar
new file mode 100644
index 0000000..47a6651
Binary files /dev/null and b/server/libraries/io/netty/netty-buffer/4.1.97.Final/netty-buffer-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-codec-haproxy/4.1.97.Final/netty-codec-haproxy-4.1.97.Final.jar b/server/libraries/io/netty/netty-codec-haproxy/4.1.97.Final/netty-codec-haproxy-4.1.97.Final.jar
new file mode 100644
index 0000000..e2bb176
Binary files /dev/null and b/server/libraries/io/netty/netty-codec-haproxy/4.1.97.Final/netty-codec-haproxy-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-codec/4.1.97.Final/netty-codec-4.1.97.Final.jar b/server/libraries/io/netty/netty-codec/4.1.97.Final/netty-codec-4.1.97.Final.jar
new file mode 100644
index 0000000..b0988ad
Binary files /dev/null and b/server/libraries/io/netty/netty-codec/4.1.97.Final/netty-codec-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-common/4.1.97.Final/netty-common-4.1.97.Final.jar b/server/libraries/io/netty/netty-common/4.1.97.Final/netty-common-4.1.97.Final.jar
new file mode 100644
index 0000000..b35e108
Binary files /dev/null and b/server/libraries/io/netty/netty-common/4.1.97.Final/netty-common-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-handler/4.1.97.Final/netty-handler-4.1.97.Final.jar b/server/libraries/io/netty/netty-handler/4.1.97.Final/netty-handler-4.1.97.Final.jar
new file mode 100644
index 0000000..222edb1
Binary files /dev/null and b/server/libraries/io/netty/netty-handler/4.1.97.Final/netty-handler-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-resolver/4.1.97.Final/netty-resolver-4.1.97.Final.jar b/server/libraries/io/netty/netty-resolver/4.1.97.Final/netty-resolver-4.1.97.Final.jar
new file mode 100644
index 0000000..301c04e
Binary files /dev/null and b/server/libraries/io/netty/netty-resolver/4.1.97.Final/netty-resolver-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-transport-classes-epoll/4.1.97.Final/netty-transport-classes-epoll-4.1.97.Final.jar b/server/libraries/io/netty/netty-transport-classes-epoll/4.1.97.Final/netty-transport-classes-epoll-4.1.97.Final.jar
new file mode 100644
index 0000000..46a18cb
Binary files /dev/null and b/server/libraries/io/netty/netty-transport-classes-epoll/4.1.97.Final/netty-transport-classes-epoll-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-aarch_64.jar b/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-aarch_64.jar
new file mode 100644
index 0000000..af13a77
Binary files /dev/null and b/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-aarch_64.jar differ
diff --git a/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-x86_64.jar b/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-x86_64.jar
new file mode 100644
index 0000000..0a600b6
Binary files /dev/null and b/server/libraries/io/netty/netty-transport-native-epoll/4.1.97.Final/netty-transport-native-epoll-4.1.97.Final-linux-x86_64.jar differ
diff --git a/server/libraries/io/netty/netty-transport-native-unix-common/4.1.97.Final/netty-transport-native-unix-common-4.1.97.Final.jar b/server/libraries/io/netty/netty-transport-native-unix-common/4.1.97.Final/netty-transport-native-unix-common-4.1.97.Final.jar
new file mode 100644
index 0000000..7347eb1
Binary files /dev/null and b/server/libraries/io/netty/netty-transport-native-unix-common/4.1.97.Final/netty-transport-native-unix-common-4.1.97.Final.jar differ
diff --git a/server/libraries/io/netty/netty-transport/4.1.97.Final/netty-transport-4.1.97.Final.jar b/server/libraries/io/netty/netty-transport/4.1.97.Final/netty-transport-4.1.97.Final.jar
new file mode 100644
index 0000000..bf0a5a7
Binary files /dev/null and b/server/libraries/io/netty/netty-transport/4.1.97.Final/netty-transport-4.1.97.Final.jar differ
diff --git a/server/libraries/io/papermc/paper/paper-api/1.20.4-R0.1-SNAPSHOT/paper-api-1.20.4-R0.1-SNAPSHOT.jar b/server/libraries/io/papermc/paper/paper-api/1.20.4-R0.1-SNAPSHOT/paper-api-1.20.4-R0.1-SNAPSHOT.jar
new file mode 100644
index 0000000..a307513
Binary files /dev/null and b/server/libraries/io/papermc/paper/paper-api/1.20.4-R0.1-SNAPSHOT/paper-api-1.20.4-R0.1-SNAPSHOT.jar differ
diff --git a/server/libraries/io/papermc/paper/paper-mojangapi/1.20.4-R0.1-SNAPSHOT/paper-mojangapi-1.20.4-R0.1-SNAPSHOT.jar b/server/libraries/io/papermc/paper/paper-mojangapi/1.20.4-R0.1-SNAPSHOT/paper-mojangapi-1.20.4-R0.1-SNAPSHOT.jar
new file mode 100644
index 0000000..8349c8f
Binary files /dev/null and b/server/libraries/io/papermc/paper/paper-mojangapi/1.20.4-R0.1-SNAPSHOT/paper-mojangapi-1.20.4-R0.1-SNAPSHOT.jar differ
diff --git a/server/libraries/it/unimi/dsi/fastutil/8.5.12/fastutil-8.5.12.jar b/server/libraries/it/unimi/dsi/fastutil/8.5.12/fastutil-8.5.12.jar
new file mode 100644
index 0000000..293bae7
Binary files /dev/null and b/server/libraries/it/unimi/dsi/fastutil/8.5.12/fastutil-8.5.12.jar differ
diff --git a/server/libraries/javax/inject/javax.inject/1/javax.inject-1.jar b/server/libraries/javax/inject/javax.inject/1/javax.inject-1.jar
new file mode 100644
index 0000000..b2a9d0b
Binary files /dev/null and b/server/libraries/javax/inject/javax.inject/1/javax.inject-1.jar differ
diff --git a/server/libraries/net/fabricmc/mapping-io/0.5.0/mapping-io-0.5.0.jar b/server/libraries/net/fabricmc/mapping-io/0.5.0/mapping-io-0.5.0.jar
new file mode 100644
index 0000000..907eb6f
Binary files /dev/null and b/server/libraries/net/fabricmc/mapping-io/0.5.0/mapping-io-0.5.0.jar differ
diff --git a/server/libraries/net/java/dev/jna/jna-platform/5.13.0/jna-platform-5.13.0.jar b/server/libraries/net/java/dev/jna/jna-platform/5.13.0/jna-platform-5.13.0.jar
new file mode 100644
index 0000000..816a567
Binary files /dev/null and b/server/libraries/net/java/dev/jna/jna-platform/5.13.0/jna-platform-5.13.0.jar differ
diff --git a/server/libraries/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar b/server/libraries/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar
new file mode 100644
index 0000000..3d49c81
Binary files /dev/null and b/server/libraries/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-api/4.15.0/adventure-api-4.15.0.jar b/server/libraries/net/kyori/adventure-api/4.15.0/adventure-api-4.15.0.jar
new file mode 100644
index 0000000..5aba67b
Binary files /dev/null and b/server/libraries/net/kyori/adventure-api/4.15.0/adventure-api-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-key/4.15.0/adventure-key-4.15.0.jar b/server/libraries/net/kyori/adventure-key/4.15.0/adventure-key-4.15.0.jar
new file mode 100644
index 0000000..c623169
Binary files /dev/null and b/server/libraries/net/kyori/adventure-key/4.15.0/adventure-key-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-logger-slf4j/4.15.0/adventure-text-logger-slf4j-4.15.0.jar b/server/libraries/net/kyori/adventure-text-logger-slf4j/4.15.0/adventure-text-logger-slf4j-4.15.0.jar
new file mode 100644
index 0000000..8fccbe8
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-logger-slf4j/4.15.0/adventure-text-logger-slf4j-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-minimessage/4.15.0/adventure-text-minimessage-4.15.0.jar b/server/libraries/net/kyori/adventure-text-minimessage/4.15.0/adventure-text-minimessage-4.15.0.jar
new file mode 100644
index 0000000..7907998
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-minimessage/4.15.0/adventure-text-minimessage-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-serializer-ansi/4.15.0/adventure-text-serializer-ansi-4.15.0.jar b/server/libraries/net/kyori/adventure-text-serializer-ansi/4.15.0/adventure-text-serializer-ansi-4.15.0.jar
new file mode 100644
index 0000000..c1cdc7c
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-serializer-ansi/4.15.0/adventure-text-serializer-ansi-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-serializer-gson/4.15.0/adventure-text-serializer-gson-4.15.0.jar b/server/libraries/net/kyori/adventure-text-serializer-gson/4.15.0/adventure-text-serializer-gson-4.15.0.jar
new file mode 100644
index 0000000..90e42e8
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-serializer-gson/4.15.0/adventure-text-serializer-gson-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-serializer-json/4.15.0/adventure-text-serializer-json-4.15.0.jar b/server/libraries/net/kyori/adventure-text-serializer-json/4.15.0/adventure-text-serializer-json-4.15.0.jar
new file mode 100644
index 0000000..a511514
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-serializer-json/4.15.0/adventure-text-serializer-json-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-serializer-legacy/4.15.0/adventure-text-serializer-legacy-4.15.0.jar b/server/libraries/net/kyori/adventure-text-serializer-legacy/4.15.0/adventure-text-serializer-legacy-4.15.0.jar
new file mode 100644
index 0000000..5386e2f
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-serializer-legacy/4.15.0/adventure-text-serializer-legacy-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/adventure-text-serializer-plain/4.15.0/adventure-text-serializer-plain-4.15.0.jar b/server/libraries/net/kyori/adventure-text-serializer-plain/4.15.0/adventure-text-serializer-plain-4.15.0.jar
new file mode 100644
index 0000000..6c68ad0
Binary files /dev/null and b/server/libraries/net/kyori/adventure-text-serializer-plain/4.15.0/adventure-text-serializer-plain-4.15.0.jar differ
diff --git a/server/libraries/net/kyori/ansi/1.0.3/ansi-1.0.3.jar b/server/libraries/net/kyori/ansi/1.0.3/ansi-1.0.3.jar
new file mode 100644
index 0000000..65c60d6
Binary files /dev/null and b/server/libraries/net/kyori/ansi/1.0.3/ansi-1.0.3.jar differ
diff --git a/server/libraries/net/kyori/examination-api/1.3.0/examination-api-1.3.0.jar b/server/libraries/net/kyori/examination-api/1.3.0/examination-api-1.3.0.jar
new file mode 100644
index 0000000..8021db0
Binary files /dev/null and b/server/libraries/net/kyori/examination-api/1.3.0/examination-api-1.3.0.jar differ
diff --git a/server/libraries/net/kyori/examination-string/1.3.0/examination-string-1.3.0.jar b/server/libraries/net/kyori/examination-string/1.3.0/examination-string-1.3.0.jar
new file mode 100644
index 0000000..0d3587e
Binary files /dev/null and b/server/libraries/net/kyori/examination-string/1.3.0/examination-string-1.3.0.jar differ
diff --git a/server/libraries/net/kyori/option/1.0.0/option-1.0.0.jar b/server/libraries/net/kyori/option/1.0.0/option-1.0.0.jar
new file mode 100644
index 0000000..d0fc8c3
Binary files /dev/null and b/server/libraries/net/kyori/option/1.0.0/option-1.0.0.jar differ
diff --git a/server/libraries/net/md-5/bungeecord-chat/1.20-R0.2-deprecated+build.18/bungeecord-chat-1.20-R0.2-deprecated+build.18.jar b/server/libraries/net/md-5/bungeecord-chat/1.20-R0.2-deprecated+build.18/bungeecord-chat-1.20-R0.2-deprecated+build.18.jar
new file mode 100644
index 0000000..221c6dd
Binary files /dev/null and b/server/libraries/net/md-5/bungeecord-chat/1.20-R0.2-deprecated+build.18/bungeecord-chat-1.20-R0.2-deprecated+build.18.jar differ
diff --git a/server/libraries/net/minecrell/terminalconsoleappender/1.3.0/terminalconsoleappender-1.3.0.jar b/server/libraries/net/minecrell/terminalconsoleappender/1.3.0/terminalconsoleappender-1.3.0.jar
new file mode 100644
index 0000000..471af96
Binary files /dev/null and b/server/libraries/net/minecrell/terminalconsoleappender/1.3.0/terminalconsoleappender-1.3.0.jar differ
diff --git a/server/libraries/net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.jar b/server/libraries/net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.jar
new file mode 100644
index 0000000..317b2b0
Binary files /dev/null and b/server/libraries/net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.jar differ
diff --git a/server/libraries/org/apache/commons/commons-lang3/3.13.0/commons-lang3-3.13.0.jar b/server/libraries/org/apache/commons/commons-lang3/3.13.0/commons-lang3-3.13.0.jar
new file mode 100644
index 0000000..891540f
Binary files /dev/null and b/server/libraries/org/apache/commons/commons-lang3/3.13.0/commons-lang3-3.13.0.jar differ
diff --git a/server/libraries/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar b/server/libraries/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar
new file mode 100644
index 0000000..2bb7c07
Binary files /dev/null and b/server/libraries/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar differ
diff --git a/server/libraries/org/apache/httpcomponents/httpcore/4.4.16/httpcore-4.4.16.jar b/server/libraries/org/apache/httpcomponents/httpcore/4.4.16/httpcore-4.4.16.jar
new file mode 100644
index 0000000..f0bdebe
Binary files /dev/null and b/server/libraries/org/apache/httpcomponents/httpcore/4.4.16/httpcore-4.4.16.jar differ
diff --git a/server/libraries/org/apache/logging/log4j/log4j-api/2.19.0/log4j-api-2.19.0.jar b/server/libraries/org/apache/logging/log4j/log4j-api/2.19.0/log4j-api-2.19.0.jar
new file mode 100644
index 0000000..e55547d
Binary files /dev/null and b/server/libraries/org/apache/logging/log4j/log4j-api/2.19.0/log4j-api-2.19.0.jar differ
diff --git a/server/libraries/org/apache/logging/log4j/log4j-core/2.19.0/log4j-core-2.19.0.jar b/server/libraries/org/apache/logging/log4j/log4j-core/2.19.0/log4j-core-2.19.0.jar
new file mode 100644
index 0000000..cdc6fe7
Binary files /dev/null and b/server/libraries/org/apache/logging/log4j/log4j-core/2.19.0/log4j-core-2.19.0.jar differ
diff --git a/server/libraries/org/apache/logging/log4j/log4j-iostreams/2.19.0/log4j-iostreams-2.19.0.jar b/server/libraries/org/apache/logging/log4j/log4j-iostreams/2.19.0/log4j-iostreams-2.19.0.jar
new file mode 100644
index 0000000..7e98300
Binary files /dev/null and b/server/libraries/org/apache/logging/log4j/log4j-iostreams/2.19.0/log4j-iostreams-2.19.0.jar differ
diff --git a/server/libraries/org/apache/logging/log4j/log4j-slf4j2-impl/2.19.0/log4j-slf4j2-impl-2.19.0.jar b/server/libraries/org/apache/logging/log4j/log4j-slf4j2-impl/2.19.0/log4j-slf4j2-impl-2.19.0.jar
new file mode 100644
index 0000000..12e226f
Binary files /dev/null and b/server/libraries/org/apache/logging/log4j/log4j-slf4j2-impl/2.19.0/log4j-slf4j2-impl-2.19.0.jar differ
diff --git a/server/libraries/org/apache/maven/maven-artifact/3.9.6/maven-artifact-3.9.6.jar b/server/libraries/org/apache/maven/maven-artifact/3.9.6/maven-artifact-3.9.6.jar
new file mode 100644
index 0000000..b695c9f
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-artifact/3.9.6/maven-artifact-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/maven-builder-support/3.9.6/maven-builder-support-3.9.6.jar b/server/libraries/org/apache/maven/maven-builder-support/3.9.6/maven-builder-support-3.9.6.jar
new file mode 100644
index 0000000..7129e8f
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-builder-support/3.9.6/maven-builder-support-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/maven-model-builder/3.9.6/maven-model-builder-3.9.6.jar b/server/libraries/org/apache/maven/maven-model-builder/3.9.6/maven-model-builder-3.9.6.jar
new file mode 100644
index 0000000..49b2dde
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-model-builder/3.9.6/maven-model-builder-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/maven-model/3.9.6/maven-model-3.9.6.jar b/server/libraries/org/apache/maven/maven-model/3.9.6/maven-model-3.9.6.jar
new file mode 100644
index 0000000..1bbc8c8
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-model/3.9.6/maven-model-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/maven-repository-metadata/3.9.6/maven-repository-metadata-3.9.6.jar b/server/libraries/org/apache/maven/maven-repository-metadata/3.9.6/maven-repository-metadata-3.9.6.jar
new file mode 100644
index 0000000..5ad525f
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-repository-metadata/3.9.6/maven-repository-metadata-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/maven-resolver-provider/3.9.6/maven-resolver-provider-3.9.6.jar b/server/libraries/org/apache/maven/maven-resolver-provider/3.9.6/maven-resolver-provider-3.9.6.jar
new file mode 100644
index 0000000..e8024e2
Binary files /dev/null and b/server/libraries/org/apache/maven/maven-resolver-provider/3.9.6/maven-resolver-provider-3.9.6.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-api/1.9.18/maven-resolver-api-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-api/1.9.18/maven-resolver-api-1.9.18.jar
new file mode 100644
index 0000000..44c03c9
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-api/1.9.18/maven-resolver-api-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-connector-basic/1.9.18/maven-resolver-connector-basic-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-connector-basic/1.9.18/maven-resolver-connector-basic-1.9.18.jar
new file mode 100644
index 0000000..0af30a5
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-connector-basic/1.9.18/maven-resolver-connector-basic-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-impl/1.9.18/maven-resolver-impl-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-impl/1.9.18/maven-resolver-impl-1.9.18.jar
new file mode 100644
index 0000000..5263984
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-impl/1.9.18/maven-resolver-impl-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-named-locks/1.9.18/maven-resolver-named-locks-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-named-locks/1.9.18/maven-resolver-named-locks-1.9.18.jar
new file mode 100644
index 0000000..e3eae74
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-named-locks/1.9.18/maven-resolver-named-locks-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-spi/1.9.18/maven-resolver-spi-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-spi/1.9.18/maven-resolver-spi-1.9.18.jar
new file mode 100644
index 0000000..b13e20b
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-spi/1.9.18/maven-resolver-spi-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-transport-http/1.9.18/maven-resolver-transport-http-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-transport-http/1.9.18/maven-resolver-transport-http-1.9.18.jar
new file mode 100644
index 0000000..a84ce3d
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-transport-http/1.9.18/maven-resolver-transport-http-1.9.18.jar differ
diff --git a/server/libraries/org/apache/maven/resolver/maven-resolver-util/1.9.18/maven-resolver-util-1.9.18.jar b/server/libraries/org/apache/maven/resolver/maven-resolver-util/1.9.18/maven-resolver-util-1.9.18.jar
new file mode 100644
index 0000000..d882859
Binary files /dev/null and b/server/libraries/org/apache/maven/resolver/maven-resolver-util/1.9.18/maven-resolver-util-1.9.18.jar differ
diff --git a/server/libraries/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar b/server/libraries/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar
new file mode 100644
index 0000000..61761fd
Binary files /dev/null and b/server/libraries/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar differ
diff --git a/server/libraries/org/codehaus/plexus/plexus-interpolation/1.26/plexus-interpolation-1.26.jar b/server/libraries/org/codehaus/plexus/plexus-interpolation/1.26/plexus-interpolation-1.26.jar
new file mode 100644
index 0000000..cfcf162
Binary files /dev/null and b/server/libraries/org/codehaus/plexus/plexus-interpolation/1.26/plexus-interpolation-1.26.jar differ
diff --git a/server/libraries/org/codehaus/plexus/plexus-utils/3.5.1/plexus-utils-3.5.1.jar b/server/libraries/org/codehaus/plexus/plexus-utils/3.5.1/plexus-utils-3.5.1.jar
new file mode 100644
index 0000000..1873c52
Binary files /dev/null and b/server/libraries/org/codehaus/plexus/plexus-utils/3.5.1/plexus-utils-3.5.1.jar differ
diff --git a/server/libraries/org/eclipse/sisu/org.eclipse.sisu.inject/0.9.0.M2/org.eclipse.sisu.inject-0.9.0.M2.jar b/server/libraries/org/eclipse/sisu/org.eclipse.sisu.inject/0.9.0.M2/org.eclipse.sisu.inject-0.9.0.M2.jar
new file mode 100644
index 0000000..7b309b7
Binary files /dev/null and b/server/libraries/org/eclipse/sisu/org.eclipse.sisu.inject/0.9.0.M2/org.eclipse.sisu.inject-0.9.0.M2.jar differ
diff --git a/server/libraries/org/fusesource/jansi/jansi/2.4.0/jansi-2.4.0.jar b/server/libraries/org/fusesource/jansi/jansi/2.4.0/jansi-2.4.0.jar
new file mode 100644
index 0000000..d6bb12f
Binary files /dev/null and b/server/libraries/org/fusesource/jansi/jansi/2.4.0/jansi-2.4.0.jar differ
diff --git a/server/libraries/org/jline/jline-reader/3.20.0/jline-reader-3.20.0.jar b/server/libraries/org/jline/jline-reader/3.20.0/jline-reader-3.20.0.jar
new file mode 100644
index 0000000..b7921f7
Binary files /dev/null and b/server/libraries/org/jline/jline-reader/3.20.0/jline-reader-3.20.0.jar differ
diff --git a/server/libraries/org/jline/jline-terminal-jansi/3.21.0/jline-terminal-jansi-3.21.0.jar b/server/libraries/org/jline/jline-terminal-jansi/3.21.0/jline-terminal-jansi-3.21.0.jar
new file mode 100644
index 0000000..94eb207
Binary files /dev/null and b/server/libraries/org/jline/jline-terminal-jansi/3.21.0/jline-terminal-jansi-3.21.0.jar differ
diff --git a/server/libraries/org/jline/jline-terminal/3.21.0/jline-terminal-3.21.0.jar b/server/libraries/org/jline/jline-terminal/3.21.0/jline-terminal-3.21.0.jar
new file mode 100644
index 0000000..d7adbc5
Binary files /dev/null and b/server/libraries/org/jline/jline-terminal/3.21.0/jline-terminal-3.21.0.jar differ
diff --git a/server/libraries/org/joml/joml/1.10.5/joml-1.10.5.jar b/server/libraries/org/joml/joml/1.10.5/joml-1.10.5.jar
new file mode 100644
index 0000000..c5fc5b9
Binary files /dev/null and b/server/libraries/org/joml/joml/1.10.5/joml-1.10.5.jar differ
diff --git a/server/libraries/org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar b/server/libraries/org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar
new file mode 100644
index 0000000..21898df
Binary files /dev/null and b/server/libraries/org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar differ
diff --git a/server/libraries/org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar b/server/libraries/org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar
new file mode 100644
index 0000000..5c6da65
Binary files /dev/null and b/server/libraries/org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar differ
diff --git a/server/libraries/org/ow2/asm/asm/9.5/asm-9.5.jar b/server/libraries/org/ow2/asm/asm/9.5/asm-9.5.jar
new file mode 100644
index 0000000..f5701dc
Binary files /dev/null and b/server/libraries/org/ow2/asm/asm/9.5/asm-9.5.jar differ
diff --git a/server/libraries/org/slf4j/jcl-over-slf4j/1.7.36/jcl-over-slf4j-1.7.36.jar b/server/libraries/org/slf4j/jcl-over-slf4j/1.7.36/jcl-over-slf4j-1.7.36.jar
new file mode 100644
index 0000000..3ecd7d5
Binary files /dev/null and b/server/libraries/org/slf4j/jcl-over-slf4j/1.7.36/jcl-over-slf4j-1.7.36.jar differ
diff --git a/server/libraries/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar b/server/libraries/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar
new file mode 100644
index 0000000..3796afe
Binary files /dev/null and b/server/libraries/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar differ
diff --git a/server/libraries/org/spongepowered/configurate-core/4.2.0-SNAPSHOT/configurate-core-4.2.0-SNAPSHOT.jar b/server/libraries/org/spongepowered/configurate-core/4.2.0-SNAPSHOT/configurate-core-4.2.0-SNAPSHOT.jar
new file mode 100644
index 0000000..3f7a3ec
Binary files /dev/null and b/server/libraries/org/spongepowered/configurate-core/4.2.0-SNAPSHOT/configurate-core-4.2.0-SNAPSHOT.jar differ
diff --git a/server/libraries/org/spongepowered/configurate-yaml/4.2.0-SNAPSHOT/configurate-yaml-4.2.0-SNAPSHOT.jar b/server/libraries/org/spongepowered/configurate-yaml/4.2.0-SNAPSHOT/configurate-yaml-4.2.0-SNAPSHOT.jar
new file mode 100644
index 0000000..da892dc
Binary files /dev/null and b/server/libraries/org/spongepowered/configurate-yaml/4.2.0-SNAPSHOT/configurate-yaml-4.2.0-SNAPSHOT.jar differ
diff --git a/server/libraries/org/xerial/sqlite-jdbc/3.42.0.1/sqlite-jdbc-3.42.0.1.jar b/server/libraries/org/xerial/sqlite-jdbc/3.42.0.1/sqlite-jdbc-3.42.0.1.jar
new file mode 100644
index 0000000..8686e3d
Binary files /dev/null and b/server/libraries/org/xerial/sqlite-jdbc/3.42.0.1/sqlite-jdbc-3.42.0.1.jar differ
diff --git a/server/libraries/org/yaml/snakeyaml/2.2/snakeyaml-2.2.jar b/server/libraries/org/yaml/snakeyaml/2.2/snakeyaml-2.2.jar
new file mode 100644
index 0000000..275dd57
Binary files /dev/null and b/server/libraries/org/yaml/snakeyaml/2.2/snakeyaml-2.2.jar differ
diff --git a/server/logs/2024-02-19-1.log.gz b/server/logs/2024-02-19-1.log.gz
new file mode 100644
index 0000000..b6772e7
Binary files /dev/null and b/server/logs/2024-02-19-1.log.gz differ
diff --git a/server/logs/2024-02-19-2.log.gz b/server/logs/2024-02-19-2.log.gz
new file mode 100644
index 0000000..5012981
Binary files /dev/null and b/server/logs/2024-02-19-2.log.gz differ
diff --git a/server/logs/2024-02-19-3.log.gz b/server/logs/2024-02-19-3.log.gz
new file mode 100644
index 0000000..8a64be9
Binary files /dev/null and b/server/logs/2024-02-19-3.log.gz differ
diff --git a/server/logs/2024-02-19-4.log.gz b/server/logs/2024-02-19-4.log.gz
new file mode 100644
index 0000000..5c3aa78
Binary files /dev/null and b/server/logs/2024-02-19-4.log.gz differ
diff --git a/server/logs/2024-02-20-1.log.gz b/server/logs/2024-02-20-1.log.gz
new file mode 100644
index 0000000..e898943
Binary files /dev/null and b/server/logs/2024-02-20-1.log.gz differ
diff --git a/server/logs/2024-02-21-1.log.gz b/server/logs/2024-02-21-1.log.gz
new file mode 100644
index 0000000..3df9f07
Binary files /dev/null and b/server/logs/2024-02-21-1.log.gz differ
diff --git a/server/logs/2024-02-21-2.log.gz b/server/logs/2024-02-21-2.log.gz
new file mode 100644
index 0000000..e1de73c
Binary files /dev/null and b/server/logs/2024-02-21-2.log.gz differ
diff --git a/server/logs/latest.log b/server/logs/latest.log
new file mode 100644
index 0000000..e8988cc
--- /dev/null
+++ b/server/logs/latest.log
@@ -0,0 +1,201 @@
+[14:28:28] [ServerMain/INFO]: Environment: Environment[sessionHost=https://sessionserver.mojang.com, servicesHost=https://api.minecraftservices.com, name=PROD]
+[14:28:33] [ServerMain/INFO]: Loaded 1174 recipes
+[14:28:34] [ServerMain/INFO]: Loaded 1271 advancements
+[14:28:34] [Server thread/INFO]: Starting minecraft server version 1.20.4
+[14:28:34] [Server thread/INFO]: Loading properties
+[14:28:34] [Server thread/INFO]: This server is running Paper version git-Paper-430 (MC: 1.20.4) (Implementing API version 1.20.4-R0.1-SNAPSHOT) (Git: 4939f87)
+[14:28:35] [Server thread/INFO]: Server Ping Player Sample Count: 12
+[14:28:35] [Server thread/INFO]: Using 4 threads for Netty based IO
+[14:28:36] [Server thread/WARN]: [!] The timings profiler has been enabled but has been scheduled for removal from Paper in the future.
+ We recommend installing the spark profiler as a replacement: https://spark.lucko.me/
+ For more information please visit: https://github.com/PaperMC/Paper/issues/8948
+[14:28:36] [Server thread/INFO]: [ChunkTaskScheduler] Chunk system is using 1 I/O threads, 2 worker threads, and gen parallelism of 2 threads
+[14:28:36] [Server thread/INFO]: Default game type: SURVIVAL
+[14:28:36] [Server thread/INFO]: Generating keypair
+[14:28:36] [Server thread/INFO]: Starting Minecraft server on *:25565
+[14:28:37] [Server thread/INFO]: Using default channel type
+[14:28:37] [Server thread/INFO]: Paper: Using Java compression from Velocity.
+[14:28:37] [Server thread/INFO]: Paper: Using Java cipher from Velocity.
+[14:28:37] [Server thread/INFO]: [ProtocolLib] Loading server plugin ProtocolLib v5.2.0-SNAPSHOT-679
+[14:28:40] [Server thread/INFO]: [Sentinel] Loading server plugin Sentinel v0.2.5
+[14:28:40] [Server thread/INFO]: [PluginManager] Loading server plugin PluginManager v2.8.1
+[14:28:40] [Server thread/INFO]: Server permissions file permissions.yml is empty, ignoring it
+[14:28:40] [Server thread/INFO]: [ProtocolLib] Enabling ProtocolLib v5.2.0-SNAPSHOT-679
+[14:28:40] [Server thread/INFO]: Preparing level "world"
+[14:28:40] [Server thread/INFO]: Preparing start region for dimension minecraft:overworld
+[14:28:41] [Server thread/INFO]: Time elapsed: 469 ms
+[14:28:41] [Server thread/INFO]: Preparing start region for dimension minecraft:the_nether
+[14:28:41] [Server thread/INFO]: Time elapsed: 54 ms
+[14:28:41] [Server thread/INFO]: Preparing start region for dimension minecraft:the_end
+[14:28:41] [Server thread/INFO]: Time elapsed: 49 ms
+[14:28:41] [Server thread/INFO]: [Sentinel] Enabling Sentinel v0.2.5
+[14:28:41] [Server thread/INFO]:
+]======------ Pre-load started! ------======[
+[14:28:41] [Server thread/INFO]: Loading Config...
+[14:28:41] [Server thread/INFO]: Loading Dictionary (en-us.json)...
+[14:28:41] [Server thread/INFO]: Loading ProtocolLib
+[14:28:41] [Server thread/INFO]: Language Status: (Sentinel language is working!)
+[14:28:41] [Server thread/INFO]: Initializing Server ID...
+[14:28:41] [Server thread/INFO]: Pre-load finished!
+]====---- Requesting Authentication ----====[
+- License Key: null
+- Server ID: 3b0a88d08c2a2320f3eb06d9a066a68d1952379417e142beb370e4e6ed6dfc58
+[14:28:42] [Server thread/INFO]: Auth Requested...
+[14:28:42] [Server thread/INFO]:
+]======----- Auth Success! -----======[
+[14:28:42] [Server thread/INFO]:
+]======----- Loading Sentinel! -----======[
+[14:28:42] [Server thread/INFO]: Starting Up! (0.2.5)...
+[14:28:42] [Server thread/INFO]: Finished!
+ ____ __ ___
+/\ _`\ /\ \__ __ /\_ \
+\ \,\L\_\ __ ___\ \ ,_\/\_\ ___ __\//\ \
+ \/_\__ \ /'__`\/' _ `\ \ \/\/\ \ /' _ `\ /'__`\\ \ \
+ /\ \L\ \/\ __//\ \/\ \ \ \_\ \ \/\ \/\ \/\ __/ \_\ \_
+ \ `\____\ \____\ \_\ \_\ \__\\ \_\ \_\ \_\ \____\/\____\
+ \/_____/\/____/\/_/\/_/\/__/ \/_/\/_/\/_/\/____/\/____/
+ ]====---- Advanced Anti-Grief & Chat Filter ----====[
+[14:28:42] [Server thread/INFO]: [PluginManager] Enabling PluginManager v2.8.1
+[14:28:42] [Server thread/INFO]: Running delayed init tasks
+[14:28:42] [Server thread/INFO]: Done (7.563s)! For help, type "help"
+[14:28:42] [Server thread/INFO]: Timings Reset
+[14:28:42] [Craft Scheduler Thread - 3 - PluginManager/INFO]: PM | You are using the latest version of PluginManager.
+[14:28:51] [Server thread/INFO]: Correct Usage: none
+[14:29:00] [Server thread/INFO]: [Sentinel] Disabling Sentinel v0.2.5
+[14:29:00] [Server thread/INFO]: Sentinel has disabled! (0.2.5) Your server is now no longer protected!
+[14:29:00] [Server thread/INFO]: PM | The plugin has been unloaded.
+[14:29:38] [Server thread/INFO]: [Sentinel] Loading server plugin Sentinel v0.2.5
+[14:29:38] [Server thread/INFO]: [Sentinel] Enabling Sentinel v0.2.5
+[14:29:38] [Server thread/INFO]:
+]======------ Pre-load started! ------======[
+[14:29:38] [Server thread/INFO]: Loading Config...
+[14:29:38] [Server thread/INFO]: Loading Dictionary (en-us.json)...
+[14:29:38] [Server thread/INFO]: Loading ProtocolLib
+[14:29:38] [Server thread/INFO]: Language Status: (Sentinel language is working!)
+[14:29:38] [Server thread/INFO]: Initializing Server ID...
+[14:29:38] [Server thread/INFO]: Pre-load finished!
+]====---- Requesting Authentication ----====[
+- License Key: null
+- Server ID: 3b0a88d08c2a2320f3eb06d9a066a68d1952379417e142beb370e4e6ed6dfc58
+[14:29:38] [Server thread/INFO]: Auth Requested...
+[14:29:38] [Server thread/INFO]:
+]======----- Auth Success! -----======[
+[14:29:38] [Server thread/INFO]:
+]======----- Loading Sentinel! -----======[
+[14:29:38] [Server thread/INFO]: Starting Up! (0.2.5)...
+[14:29:38] [Server thread/INFO]: Finished!
+ ____ __ ___
+/\ _`\ /\ \__ __ /\_ \
+\ \,\L\_\ __ ___\ \ ,_\/\_\ ___ __\//\ \
+ \/_\__ \ /'__`\/' _ `\ \ \/\/\ \ /' _ `\ /'__`\\ \ \
+ /\ \L\ \/\ __//\ \/\ \ \ \_\ \ \/\ \/\ \/\ __/ \_\ \_
+ \ `\____\ \____\ \_\ \_\ \__\\ \_\ \_\ \_\ \____\/\____\
+ \/_____/\/____/\/_/\/_/\/__/ \/_/\/_/\/_/\/____/\/____/
+ ]====---- Advanced Anti-Grief & Chat Filter ----====[
+[14:29:38] [Server thread/INFO]: PM | The plugin has been loaded.
+[14:29:47] [User Authenticator #0/INFO]: UUID of player obvWolf is 049460f7-21cb-42f5-8059-d42752bf406f
+[14:29:48] [Server thread/INFO]: obvWolf joined the game
+[14:29:48] [Server thread/INFO]: obvWolf[/127.0.0.1:56607] logged in with entity id 363 at ([world]35.81923900676791, 65.0, -17.30000001192093)
+[14:30:10] [Server thread/INFO]: obvWolf issued server command: /sentinel debug chat sentanal anti nuook
+[14:30:11] [Server thread/INFO]: obvWolf issued server command: /sentinelcallback fpreport 20240221143010067
+[14:30:27] [Server thread/INFO]: [Sentinel] Disabling Sentinel v0.2.5
+[14:30:27] [Server thread/INFO]: Sentinel has disabled! (0.2.5) Your server is now no longer protected!
+[14:30:27] [Server thread/INFO]: PM | The plugin has been unloaded.
+[14:30:47] [Server thread/INFO]: [Sentinel] Loading server plugin Sentinel v0.2.5
+[14:30:47] [Server thread/INFO]: [Sentinel] Enabling Sentinel v0.2.5
+[14:30:47] [Server thread/INFO]:
+]======------ Pre-load started! ------======[
+[14:30:47] [Server thread/INFO]: Loading Config...
+[14:30:47] [Server thread/INFO]: Loading Dictionary (en-us.json)...
+[14:30:47] [Server thread/INFO]: Loading ProtocolLib
+[14:30:47] [Server thread/INFO]: Language Status: (Sentinel language is working!)
+[14:30:47] [Server thread/INFO]: Initializing Server ID...
+[14:30:47] [Server thread/INFO]: Pre-load finished!
+]====---- Requesting Authentication ----====[
+- License Key: null
+- Server ID: 3b0a88d08c2a2320f3eb06d9a066a68d1952379417e142beb370e4e6ed6dfc58
+[14:30:47] [Server thread/INFO]: Auth Requested...
+[14:30:47] [Server thread/INFO]:
+]======----- Auth Success! -----======[
+[14:30:47] [Server thread/INFO]:
+]======----- Loading Sentinel! -----======[
+[14:30:47] [Server thread/INFO]: Starting Up! (0.2.5)...
+[14:30:47] [Server thread/INFO]: Finished!
+ ____ __ ___
+/\ _`\ /\ \__ __ /\_ \
+\ \,\L\_\ __ ___\ \ ,_\/\_\ ___ __\//\ \
+ \/_\__ \ /'__`\/' _ `\ \ \/\/\ \ /' _ `\ /'__`\\ \ \
+ /\ \L\ \/\ __//\ \/\ \ \ \_\ \ \/\ \/\ \/\ __/ \_\ \_
+ \ `\____\ \____\ \_\ \_\ \__\\ \_\ \_\ \_\ \____\/\____\
+ \/_____/\/____/\/_/\/_/\/__/ \/_/\/_/\/_/\/____/\/____/
+ ]====---- Advanced Anti-Grief & Chat Filter ----====[
+[14:30:47] [Server thread/INFO]: PM | The plugin has been loaded.
+[14:30:51] [Server thread/INFO]: obvWolf issued server command: /sentinel debug chat sentanal anti nuook
+[14:30:52] [Server thread/INFO]: obvWolf issued server command: /sentinelcallback fpreport 20240221143051429
+[14:30:52] [Server thread/WARN]: java.lang.NullPointerException: Cannot invoke "io.github.thetrouper.sentinel.data.Report.event()" because "report" is null
+[14:30:52] [Server thread/WARN]: at Sentinel-0.2.5.jar//io.github.thetrouper.sentinel.server.functions.ReportFalsePositives.sendFalsePositiveReport(ReportFalsePositives.java:57)
+[14:30:52] [Server thread/WARN]: at Sentinel-0.2.5.jar//io.github.thetrouper.sentinel.cmds.ChatClickCallback.dispatchCommand(ChatClickCallback.java:27)
+[14:30:52] [Server thread/WARN]: at Sentinel-0.2.5.jar//io.github.itzispyder.pdk.commands.CustomCommand.onCommand(CustomCommand.java:49)
+[14:30:52] [Server thread/WARN]: at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45)
+[14:30:52] [Server thread/WARN]: at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:155)
+[14:30:52] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_20_R3.CraftServer.dispatchCommand(CraftServer.java:999)
+[14:30:52] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_20_R3.command.BukkitCommandWrapper.run(BukkitCommandWrapper.java:64)
+[14:30:52] [Server thread/WARN]: at com.mojang.brigadier.context.ContextChain.runExecutable(ContextChain.java:73)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.execution.tasks.ExecuteCommand.a(ExecuteCommand.java:32)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.execution.tasks.ExecuteCommand.execute(ExecuteCommand.java:19)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.execution.UnboundEntryAction.a(UnboundEntryAction.java:8)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.execution.CommandQueueEntry.a(CommandQueueEntry.java:5)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.execution.ExecutionContext.a(ExecutionContext.java:101)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.CommandDispatcher.a(CommandDispatcher.java:434)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.CommandDispatcher.performCommand(CommandDispatcher.java:336)
+[14:30:52] [Server thread/WARN]: at net.minecraft.commands.CommandDispatcher.a(CommandDispatcher.java:323)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:2230)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.network.PlayerConnection.lambda$handleChatCommand$14(PlayerConnection.java:2190)
+[14:30:52] [Server thread/WARN]: at net.minecraft.util.thread.IAsyncTaskHandler.b(IAsyncTaskHandler.java:59)
+[14:30:52] [Server thread/WARN]: at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.TickTask.run(TickTask.java:18)
+[14:30:52] [Server thread/WARN]: at net.minecraft.util.thread.IAsyncTaskHandler.d(IAsyncTaskHandler.java:153)
+[14:30:52] [Server thread/WARN]: at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.d(IAsyncTaskHandlerReentrant.java:24)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1455)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:194)
+[14:30:52] [Server thread/WARN]: at net.minecraft.util.thread.IAsyncTaskHandler.x(IAsyncTaskHandler.java:126)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.bl(MinecraftServer.java:1432)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1355)
+[14:30:52] [Server thread/WARN]: at net.minecraft.util.thread.IAsyncTaskHandler.c(IAsyncTaskHandler.java:136)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.w_(MinecraftServer.java:1333)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1222)
+[14:30:52] [Server thread/WARN]: at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:319)
+[14:30:52] [Server thread/WARN]: at java.base/java.lang.Thread.run(Thread.java:840)
+[14:31:15] [Server thread/INFO]: obvWolf lost connection: Disconnected
+[14:31:15] [Server thread/INFO]: obvWolf left the game
+[14:32:46] [Server thread/WARN]: Can't keep up! Is the server overloaded? Running 21277ms or 425 ticks behind
+[15:06:57] [Server thread/INFO]: Stopping the server
+[15:06:57] [Server thread/INFO]: Stopping server
+[15:06:57] [Server thread/INFO]: [Sentinel] Disabling Sentinel v0.2.5
+[15:06:57] [Server thread/INFO]: Sentinel has disabled! (0.2.5) Your server is now no longer protected!
+[15:06:57] [Server thread/INFO]: [PluginManager] Disabling PluginManager v2.8.1
+[15:06:57] [Server thread/INFO]: [ProtocolLib] Disabling ProtocolLib v5.2.0-SNAPSHOT-679
+[15:06:57] [Server thread/INFO]: Saving players
+[15:06:57] [Server thread/INFO]: Saving worlds
+[15:06:57] [Server thread/INFO]: Saving chunks for level 'ServerLevel[world]'/minecraft:overworld
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Waiting 60s for chunk system to halt for world 'world'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Halted chunk system for world 'world'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Saving all chunkholders for world 'world'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Saved 1 block chunks, 132 entity chunks, 0 poi chunks in world 'world' in 0.04s
+[15:06:57] [Server thread/INFO]: ThreadedAnvilChunkStorage (world): All chunks are saved
+[15:06:57] [Server thread/INFO]: Saving chunks for level 'ServerLevel[world_nether]'/minecraft:the_nether
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Waiting 60s for chunk system to halt for world 'world_nether'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Halted chunk system for world 'world_nether'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Saving all chunkholders for world 'world_nether'
+[15:06:57] [Server thread/INFO]: [ChunkHolderManager] Saved 0 block chunks, 8 entity chunks, 0 poi chunks in world 'world_nether' in 0.00s
+[15:06:58] [Server thread/INFO]: ThreadedAnvilChunkStorage (DIM-1): All chunks are saved
+[15:06:58] [Server thread/INFO]: Saving chunks for level 'ServerLevel[world_the_end]'/minecraft:the_end
+[15:06:58] [Server thread/INFO]: [ChunkHolderManager] Waiting 60s for chunk system to halt for world 'world_the_end'
+[15:06:58] [Server thread/INFO]: [ChunkHolderManager] Halted chunk system for world 'world_the_end'
+[15:06:58] [Server thread/INFO]: [ChunkHolderManager] Saving all chunkholders for world 'world_the_end'
+[15:06:58] [Server thread/INFO]: [ChunkHolderManager] Saved 0 block chunks, 10 entity chunks, 0 poi chunks in world 'world_the_end' in 0.00s
+[15:06:58] [Server thread/INFO]: ThreadedAnvilChunkStorage (DIM1): All chunks are saved
+[15:06:58] [Server thread/INFO]: ThreadedAnvilChunkStorage: All dimensions are saved
+[15:06:58] [Server thread/INFO]: Flushing Chunk IO
+[15:06:58] [Server thread/INFO]: Closing Thread Pool
+[15:06:58] [Server thread/INFO]: Closing Server
diff --git a/server/ops.json b/server/ops.json
new file mode 100644
index 0000000..09eb9c2
--- /dev/null
+++ b/server/ops.json
@@ -0,0 +1,8 @@
+[
+ {
+ "uuid": "049460f7-21cb-42f5-8059-d42752bf406f",
+ "name": "obvWolf",
+ "level": 4,
+ "bypassesPlayerLimit": false
+ }
+]
\ No newline at end of file
diff --git a/server/permissions.yml b/server/permissions.yml
new file mode 100644
index 0000000..e69de29
diff --git a/server/plugins/PluginManager.jar b/server/plugins/PluginManager.jar
new file mode 100644
index 0000000..56eebf2
Binary files /dev/null and b/server/plugins/PluginManager.jar differ
diff --git a/server/plugins/PluginManager/config.yml b/server/plugins/PluginManager/config.yml
new file mode 100644
index 0000000..6b15296
--- /dev/null
+++ b/server/plugins/PluginManager/config.yml
@@ -0,0 +1,36 @@
+#When loading plugins ignore files that don't end with .jar
+#Default: false
+IgnoreNonJarPlugins: true
+
+#The user agent used to make web requests
+UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like
+ Gecko) Chrome/75.0.3770.100 Safari/537.36
+
+#A list of plugins which should be ignored by batch actions
+#Default: [PluginManager]
+IgnoredPlugins:
+- PluginManager
+
+#Check for PluginManager updates on startup
+#Default: true
+CheckForUpdates: true
+
+#Automatically download the latest PluginManager version
+#Default: true
+AutoUpdate: true
+
+#Hide the PluginManager commands from a player if he/she does not have permission for it
+#Default: false
+HideNoPermissionCommands: true
+
+#Automatically reload the updated plugins
+#default: false
+AutoReloadUpdated: false
+
+#Allow the use of batch actions
+#Default: true
+AllowBatchActions: true
+
+#Only allow the use of pm through console
+#Default: false
+OnlyConsole: false
diff --git a/server/plugins/PluginManager/installed.yml b/server/plugins/PluginManager/installed.yml
new file mode 100644
index 0000000..48be9eb
--- /dev/null
+++ b/server/plugins/PluginManager/installed.yml
@@ -0,0 +1,2 @@
+Plugins: {}
+PluginNames: []
diff --git a/server/plugins/PluginManager/messages.lang b/server/plugins/PluginManager/messages.lang
new file mode 100644
index 0000000..981905d
--- /dev/null
+++ b/server/plugins/PluginManager/messages.lang
@@ -0,0 +1,193 @@
+# Translations for PluginManager
+# Use & for color codes. Use && for &
+# Use %1/%2/%... for arguments
+# Use # for comments. They are not supported at the end of the line as you may use # in translations
+# The default color of messages is &a (green)
+# Some translations support multiple lines. To split the individual lines use \n
+# If you have missing translations they will automatically get added to the end of the file and a notification will appear in the console
+
+# General translations
+pm.general.noPermission=&cI'm sorry but you don't have access to this command.
+pm.general.pluginNotFound=&cThe plugin could not be found
+pm.general.checkConsole=Check console
+pm.general.onlyPlayer=&cYou have to run this command as a player.
+pm.general.onlyConsole=&cIngame commands are disabled. Please use the console.
+
+# Soft depends
+pm.softdepend.found=The soft depend &6%1 &ais installed and will be used.
+
+# Updater
+pm.updater.found=A new update of &6PluginManager &ais available &e(%1 -> %2)&a.
+pm.updater.newMajor=&c------------------------------\nA new &lmajor update &aof &6PluginManager &ais available &e(%1 -> %2)&a.\nCheck the Github/SpigotMC page for more information about this new Version.\n&c------------------------------
+pm.updater.downloadSuccess=Successfully downloaded new &6PluginManager &aversion.
+pm.updater.checkChangelog=You should check out the changelog here &6%1&a.
+pm.updater.selfReload=PluginManager is reloading itself in some seconds...
+pm.updater.reloadSuccess=PluginManager successfully reloaded itself!
+pm.updater.downloadFail=&cCould not auto download the latest &6PluginManager &cversion.
+pm.updater.downloadHere=You can download it here: &6%1
+pm.updater.latestVersion=You are using the latest version of &6PluginManager&a.
+pm.updater.error=&cAn unknown error occurred whilst checking for a new &6PluginManager &cversion!.
+pm.updater.missingTranslations=&cYou have missing translations in your &6messages.lang &cfile\nIf you just installed an update this is normal and can be ignored if you do not want custom translations
+
+# Installed plugins
+pm.installedPlugins.notFound=&cThe plugin &6%1 &chas been removed from the config because the file could not be found anymore.
+
+# PluginUtils
+# loadPlugin method
+pm.pluginutils.loadPlugin.fileNotFound=Plugin file not found
+pm.pluginutils.loadPlugin.missingDependency=Missing Dependency
+pm.pluginutils.loadPlugin.invalidPluginFile=Invalid plugin file
+pm.pluginutils.loadPlugin.invalidPluginDescription=Invalid plugin description
+pm.pluginutils.loadPlugin.notAdded=Unable to add to plugin list
+# unloadPlugin method
+pm.pluginutils.unloadPlugin.pluginListError=Unable to get plugins list
+pm.pluginutils.unloadPlugin.lookupNamesError=Unable to get lookup names
+pm.pluginutils.unloadPlugin.commandMapError=Unable to get command map
+pm.pluginutils.unloadPlugin.knownCommandsError=Unable to get known commands
+pm.pluginutils.unloadPlugin.closeClassLoaderError=Unable to close the class loader
+pm.pluginutils.unloadPlugin.unknownClassLoader=&cIt seems like spigot no longer uses URLClassLoader.\n&cPlease report this to the plugin dev!
+
+# Installed plugins config
+pm.installedpluginsconfig.createError=Unable to create installed.yml file!
+pm.installedpluginsconfig.loadError=Unable to load installed.yml file!
+pm.installedpluginsconfig.saveError=Unable to save installed.yml file!
+
+# Commands
+# Reload command
+pm.commands.reload.start=&aReloading all plugins...
+pm.commands.reload.done=&aAll plugins have been reloaded.
+pm.commands.reload.unloadError=&cCould not unload plugin &6%1&c. &7(%2)
+pm.commands.reload.loadError=&cCould not load plugin &6%1&c. &7(%2)
+# PluginManager command
+pm.commands.pluginmanager.subNotFound=&cThe command could not be found.
+pm.commands.pluginmanager.invalidUsage=&cInvalid command usage!
+pm.commands.pluginmanager.correctUsage=Use: &6pm %1
+pm.commands.pluginmanager.unknownException=&cAn unknown error occurred whilst executing this command!\n&cPlease contact the developer of this plugin and provide a copy of the log.
+# Sub commands
+# Commands sub
+pm.subcommands.commands.noCommands=&cThe plugin &6%1 &chas no commands registered.
+pm.subcommands.commands.commandsOf=&6Commands of &a%1&6:
+pm.subcommands.commands.help=Show a list of all commands registered by a given plugin.\nIt is only possible to show commands which are registered using the "normal" way of adding them to the plugin.yml.\nAll commands registered differently by eg. using events can not be listed by PluginManager!
+# Delete sub
+pm.subcommands.delete.unloadError=&cThe plugin could not be unloaded. &7(%2)
+pm.subcommands.delete.fileNotFound=&cThe file of the plugin could not be found.
+pm.subcommands.delete.success=The plugin has been deleted.
+pm.subcommands.delete.deleteError=&cThe plugin could not be deleted.
+pm.subcommands.delete.overwriteError=Plugin could not be overwritten
+pm.subcommands.delete.nextStartDelete=It will get deleted on the next restart.
+pm.subcommands.delete.manualDelete=&cPluginManger tried to overwrite it but this failed too.\n&cYou sadly have to delete it manually.
+pm.subcommands.delete.help=Unload and delete a plugin directly from the server.\nIf the plugin could not be deleted because of access restrictions it will be overwritten with an empty file and get deleted the next time if possible.\nIf this fails too there is no way for PluginManager to delete the plugin so you have to do it manually.
+# Disable sub
+pm.subcommands.disable.disableError=&cCould not disable the plugin &6%1&c. &7(%2)
+pm.subcommands.disable.batchSuccess=Disabled all plugins &e(%1)&a.
+pm.subcommands.disable.singleSuccess=The plugin &6%1 &ahas been disabled.
+pm.subcommands.disable.alreadyDisabled=&cThe plugin &6%1 &cis already disabled.
+pm.subcommands.disable.help=Disable a plugin to stop it from executing.\nYou can easily enable it again using '/pm enable'.
+# Download sub
+pm.subcommands.download.success=Successfully downloaded the plugin and saved it as &6%1&a.
+pm.subcommands.download.downloadError=&cCould not download the plugin &6%1&c. &7(%2)
+pm.subcommands.download.idExtractError=&cCould not extract the plugin id from the url.\n&aYou can try entering the id manually. You can find the id here:\n&6https://www.spigotmc.org/resources/plugin-name.&aID&6/
+pm.subcommands.download.externalLink=&cThe plugin has an external download link and can not be downloaded automatically.
+pm.subcommands.download.notJar=&cThe plugin is not a jar file. File type: &6%1
+pm.subcommands.download.notBought=&cIt seems like you don't have bought this plugin.\n&aThe price is &6%1&a.
+pm.subcommands.download.isPremium=&cThe plugin is a premium resource and can not be downloaded automatically.\n&aThe price is &6%1&a.
+pm.subcommands.download.updateConfigError=&cCould not add plugin into config for later updates.
+pm.subcommands.download.noDownload=&cThe plugin could not be found or has no download.
+pm.subcommands.download.spigetError=&cCould not reach the spiget api. Please try again later. &7(%1)
+pm.subcommands.download.help=Download a plugin ingame from spigotmc or a direct link.\nIf the plugin is downloaded from spigotmc the current version is getting saved so you can easily update it using '/pm update' in the future.\nFor spigotmc downloads you can paste the url of the plugin so PluginManager extracts the id directly from the url but you can also just paste it there manually.\nThe id can be found at the end of the url: https://www.spigotmc.org/resources/plugin-name._ID_/
+# Dump sub
+pm.subcommands.dump.noBatchPermission=&cThe file for &6%1 &ccould not be written. Do you have write access to the server folder? &7(%2)
+pm.subcommands.dump.batchSuccess=Successfully dumped all Plugin infos. You can find them in the &6plugin_dumps &afolder.
+pm.subcommands.dump.success=Successfully dumped Plugin infos. You can find it in the &6plugin_dumps &afolder.
+pm.subcommands.dump.noPermission=&cThe file could not be written. Do you have write access to the server folder? &7(%1)
+pm.subcommands.dump.help=Dump all infos about a plugin to a file in the server folder to get an easy overview of all installed plugins and their permissions/commands.\nThe info contains the following things:\n - Name\n - Description\n - Version\n - Author(s)\n - Website\n - Prefix\n - Commands\n - Permissions with defaults and children
+pm.subcommands.dump.name=Name: %1
+pm.subcommands.dump.description=Description: %1
+pm.subcommands.dump.version=Version: %1
+pm.subcommands.dump.authors=Author(s): %1
+pm.subcommands.dump.website=Website: %1
+pm.subcommands.dump.prefix=Prefix: %1
+pm.subcommands.dump.commands=Commands:
+pm.subcommands.dump.permissions=Permissions:
+pm.subcommands.dump.default=Default: %1
+pm.subcommands.dump.childPermissions=Child Permissions:
+# Enable sub
+pm.subcommands.enable.enableError=&cCould not enable the plugin &6%1&c. &7(%2)
+pm.subcommands.enable.batchSuccess=Enabled all plugins &e(%1)&a.
+pm.subcommands.enable.success=The plugin &6%1 &ahas been enabled.
+pm.subcommands.enable.alreadyEnabled=&cThe plugin &6%1 &cis already enabled.
+pm.subcommands.enable.help=Enable a plugin to use it again.\nYou can easily disable it again using '/pm disable'.
+# Find sub
+pm.subcommands.find.noPlugin=&cThere is no plugin which has this command registered.
+pm.subcommands.find.listHeader=&6The plugins with this command:
+pm.subcommands.find.help=Find the plugin which registered a specified command.\nIt is only possible to find commands which are registered using the "normal" way of adding them to the plugin.yml.\nAll commands registered differently by eg. using events can not be listed by PluginManager!
+# Gui sub
+pm.subcommands.gui.help=Show an easy to use gui to execute all plugin specific commands without actually executing them.
+pm.subcommands.gui.page=Page
+pm.subcommands.gui.backToPage=Back to page
+pm.subcommands.gui.goToPage=Go to page
+pm.subcommands.gui.back=Back
+# Help sub
+pm.subcommands.help.header=&6---------- Help for &a%1 &6----------
+pm.subcommands.help.help=Show detailed information about all sub commands so you can see all important aspects directly without specifically searching for them.
+# Info sub
+pm.subcommands.info.pluginInfo=&6Plugin Info:
+pm.subcommands.info.name=&aName: &6%1
+pm.subcommands.info.description=&aDescription: &6%1
+pm.subcommands.info.version=&aVersion: &6%1
+pm.subcommands.info.authors=&aAuthor(s): &6%1
+pm.subcommands.info.pluginEnabled=&aThe plugin is currently &aenabled
+pm.subcommands.info.pluginDisabled=&aThe plugin is currently &cdisabled
+pm.subcommands.info.help=View some infos about a give command.\nFollowing things get shown:\n - Name\n - Description\n - Version\n - Author(s)\n - Plugin status (enabled/disabled)
+# List sub
+pm.subcommands.list.header=&6Plugins &e&o(%1)&6:
+pm.subcommands.list.help=Show a list of all installed plugins and their status (enabled/disabled).
+# Load sub
+pm.subcommands.load.loadError=&cCould not load the plugin &6%1&c. &7(%2)
+pm.subcommands.load.batchSuccess=Loaded all plugins &e(%1)&a.
+pm.subcommands.load.alreadyLoaded=&cThe plugin is already loaded.
+pm.subcommands.load.success=The plugin has been loaded.
+pm.subcommands.load.help=Load a plugin which is not yet loaded.\nYou can enter the file name (if it does not contain spaces) or the name in the plugin.yml.
+# Permissions sub
+pm.subcommands.permissions.noPermissions=&cThe plugin does not have permissions registered.
+pm.subcommands.permissions.header=&6Permissions of &a%1&6:
+pm.subcommands.permissions.description=Description
+pm.subcommands.permissions.default=Default
+pm.subcommands.permissions.everybody=Everybody
+pm.subcommands.permissions.nobody=Nobody
+pm.subcommands.permissions.ops=OPs
+pm.subcommands.permissions.notOps=Not OPs
+pm.subcommands.permissions.undefined=Undefined
+pm.subcommands.permissions.childPermissions=Child Permissions
+pm.subcommands.permissions.help=List all permissions by a plugin.\nIt is only possible to show permissions which are listed in the plugin.yml.
+# Reload sub
+pm.subcommands.reload.success=The plugin &6%1 &ahas been reloaded.
+pm.subcommands.reload.help=Unload and load a plugin again to release all its loaded resources and update it during runtime or try to fix some issues.
+# ReloadConfig sub
+pm.subcommands.reloadconfig.batchSuccess=Reloaded the config of all plugins &e(%1)&a.
+pm.subcommands.reloadconfig.success=The config of the plugin &6%1 &ahas been reloaded.
+pm.subcommands.reloadconfig.help=Reload the config of a given plugin.\nYou can easily reload the config of other plugins even if they do not have an own reload config command.\nThis may have no effect on some plugins if they cache config values or need other things executed on a config reload.
+# Restart sub
+pm.subcommands.restart.batchSuccess=Restarted all plugins &e(%1)&a.
+pm.subcommands.restart.success=The plugin &6%1 &ahas been restarted.
+pm.subcommands.restart.help=Enable and disable a plugin to release all its loaded resources (eg. config files).\nThis does not reload the classes and actually can break many plugins which can not be restarted!
+# Unload sub
+pm.subcommands.unload.unloadError=&cCould not unload the plugin &6%1&c. &7(%2)
+pm.subcommands.unload.batchSuccess=Unloaded all plugins &e(%1)&a.
+pm.subcommands.unload.success=The plugin has been unloaded.
+pm.subcommands.unload.help=Unload a plugin and release all its loaded resources.\nIf you are testing new plugins you can just unload them again if they do not fit your needs.
+# Update sub
+pm.subcommands.update.batchSuccess=Successfully updated the plugin &6%1 &ato the newest version.
+pm.subcommands.update.batchUpToDate=The plugin &6%1 &ais already up to date.
+pm.subcommands.update.batchSpigetError=&cCould not reach the spiget api or plugin &6%1 &cis not on spigotmc. Please try again later.
+pm.subcommands.update.batchWriteError=&cCould not save the plugin file of &6%1&c.
+pm.subcommands.update.batchDone=Checked all plugins in the config for updates.
+pm.subcommands.update.success=Successfully updated the plugin to the newest version.
+pm.subcommands.update.upToDate=The plugin is already up to date.
+pm.subcommands.update.notInConfig=&cThe plugin &6%1 &cis not in the config file.
+pm.subcommands.update.spigetError=&cCould not reach the spiget api or plugin is not on spigotmc. Please try again later.
+pm.subcommands.update.writeError=&cCould not save the plugin file.
+pm.subcommands.update.error=&cCould not update the plugin &6%1&c. &7(%2)
+pm.subcommands.update.nameUpdateAvailable=The plugin &6%1 &ahas an update available.
+pm.subcommands.update.updateAvailable=The plugin has an update available.
+pm.subcommands.update.help=Update plugins previously downloaded using the '/pm download' command.\nThis only works with plugins from spigotmc.
diff --git a/server/plugins/ProtocolLib.jar b/server/plugins/ProtocolLib.jar
new file mode 100644
index 0000000..d93f3c1
Binary files /dev/null and b/server/plugins/ProtocolLib.jar differ
diff --git a/server/plugins/ProtocolLib/config.yml b/server/plugins/ProtocolLib/config.yml
new file mode 100644
index 0000000..6bf6d62
--- /dev/null
+++ b/server/plugins/ProtocolLib/config.yml
@@ -0,0 +1,30 @@
+global:
+ # Settings for the automatic version updater
+ auto updater:
+ notify: true
+ download: false
+
+ # Number of seconds to wait until a new update is downloaded
+ delay: 43200 # 12 hours
+
+ metrics: true
+
+ # Prints certain warnings to players with the protocol.info permission
+ chat warnings: true
+
+ # Automatically compile structure modifiers
+ background compiler: true
+
+ # Disable version checking for the given Minecraft version. Backup your world first!
+ ignore version check:
+
+ # Whether or not to enable the filter command
+ debug: false
+
+ # Whether or not to print a stack trace for every warning
+ detailed error: false
+
+ # The engine used by the filter command
+ script engine: JavaScript
+
+ suppressed reports:
\ No newline at end of file
diff --git a/server/plugins/ProtocolLib/lastupdate b/server/plugins/ProtocolLib/lastupdate
new file mode 100644
index 0000000..e5700ab
--- /dev/null
+++ b/server/plugins/ProtocolLib/lastupdate
@@ -0,0 +1 @@
+1708540852
\ No newline at end of file
diff --git a/server/plugins/Sentinel-0.2.5.jar b/server/plugins/Sentinel-0.2.5.jar
new file mode 100644
index 0000000..ccabc24
Binary files /dev/null and b/server/plugins/Sentinel-0.2.5.jar differ
diff --git a/server/plugins/Sentinel/advanced-config.json b/server/plugins/Sentinel/advanced-config.json
new file mode 100644
index 0000000..4f1aa9d
--- /dev/null
+++ b/server/plugins/Sentinel/advanced-config.json
@@ -0,0 +1,61 @@
+{
+ "fakePlugins": [
+ "This server wishes to keep their plugins confidential. Anyways, Enjoy your meteor client! If the owner is incompetent, then .server plugins MassScan should still work ;)",
+ "NoCheatPlus",
+ "Negativity",
+ "Warden",
+ "Horizon",
+ "Illegalstack",
+ "CoreProtect",
+ "ExploitsX",
+ "Vulcan (Outdated version frfr)",
+ "ABC",
+ "Spartan",
+ "Kauri",
+ "AnticheatReloaded",
+ "WitherAC",
+ "GodsEye",
+ "Matrix",
+ "Wraith",
+ "AntiXrayHeuristics",
+ "GrimAC"
+ ],
+ "versionAliases": [
+ "version",
+ "ver",
+ "about",
+ "bukkit:version",
+ "bukkit:ver",
+ "bukkit:about",
+ "?",
+ "bukkit:?",
+ "pl",
+ "bukkit:pl",
+ "plugins",
+ "bukkit:plugins",
+ "bukkit:help"
+ ],
+ "leetPatterns": {
+ "@": "a",
+ "!": "i",
+ "#": "h",
+ "$": "s",
+ "+": "t",
+ "0": "o",
+ "1": "i",
+ "3": "e",
+ "4": "a",
+ "5": "s",
+ "6": "g",
+ "V": "u",
+ "v": "u",
+ "7": "l",
+ "|": "i",
+ "\u003c": "c"
+ },
+ "allowedCharRegex": "[A-Za-z0-9\\[,./?\u003e\u003c|\\]§()*\u0026^%$#@!~`{}:;\u0027\"-_]",
+ "falsePosRegex": "",
+ "swearRegex": "",
+ "strictRegex": "",
+ "urlRegex": "(?:https?://)?(?:www.)?(?:(?\u003csubdomain\u003e[a-z0-9-]+).)?(?\u003cdomain\u003e[a-z0-9-]+).(?:(?\u003ctld\u003e[a-z]{1,63}))?(?::(?\u003cport\u003e[0-9]{1,5}))?(?:[/#](?\u003cpath\u003e[A-Za-z0-9_/.~:/?#\\[\\]@!$\u0026\u0027()*+,;\u003d.]*)?)?"
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/false-positives.json b/server/plugins/Sentinel/false-positives.json
new file mode 100644
index 0000000..ba2b095
--- /dev/null
+++ b/server/plugins/Sentinel/false-positives.json
@@ -0,0 +1,58 @@
+{
+ "swearWhitelist": [
+ "but then",
+ "was scamming",
+ "an alt",
+ "can also",
+ "analysis",
+ "analytics",
+ "arsenal",
+ "assassin",
+ "as saying",
+ "assert",
+ "assign",
+ "assimil",
+ "assist",
+ "associat",
+ "assum",
+ "assur",
+ "basement",
+ "bass",
+ "cass",
+ "butter",
+ "canvass",
+ "cocktail",
+ "cumber",
+ "document",
+ "evaluate",
+ "exclusive",
+ "expensive",
+ "explain",
+ "expression",
+ "grape",
+ "grass",
+ "harass",
+ "hotwater",
+ "identit",
+ "kassa",
+ "kassi",
+ "lass",
+ "leafage",
+ "libshitz",
+ "magnacumlaude",
+ "mass",
+ "mocha",
+ "pass",
+ "phoebe",
+ "phoenix",
+ "push it",
+ "sassy",
+ "saturday",
+ "scrap",
+ "serfage",
+ "sexist",
+ "shoe",
+ "stitch",
+ "therapist"
+ ]
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/lang/en-us.json b/server/plugins/Sentinel/lang/en-us.json
new file mode 100644
index 0000000..256e65d
--- /dev/null
+++ b/server/plugins/Sentinel/lang/en-us.json
@@ -0,0 +1,44 @@
+{
+ "dictionary": {
+ "no-message-provided": "§cYou must provide a message to send!",
+ "spy-message": "§d§lSpy §8» §b§n%1$s§7 has messaged §b§n%2$s§7.",
+ "spam-notification-hover": "§8]\u003d\u003d-- §d§lSentinel §8--\u003d\u003d[\n§bPrevious: §f%1$s\n§bCurrent: §f%2$s\n§bSimilarity §f%3$s",
+ "profanity-mute-notification": "§b§n%1$s§7 has been auto-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
+ "spam-mute-warn": "§cYou have been auto-punished for violating the anti-spam repetitively!",
+ "url-notification-hover": "§8]\u003d\u003d-- §d§lSentinel §8--\u003d\u003d[\n§bDetected: %1$s",
+ "log-already-op": "The permissions of %s are already elevated! Retrying...",
+ "no-user-reply": "§cYou have nobody to reply to!",
+ "action-automatic": "§7This action was preformed automatically\n§7by the §bSentinel Anti-Spam§7 algorithm.",
+ "no-plugins-for-u": "§cThis server wishes to keep their plugins confidential.",
+ "profanity-filter-notification-hover": "§8]\u003d\u003d-- §d§lSentinel §8--\u003d\u003d[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§8§o(Click to report false positive)",
+ "message-sent": "§d§lMessage §8» §b[§fYou §e\u003e§f %1$s§b] §7%2$s",
+ "url-warn": "§cDo not send urls in chat!",
+ "profanity-mute-warn": "You have been auto-muted for repeated violation of the profanity filter! §7§o(Hover for more info)",
+ "slur-mute-notification": "§b§n%1$s§7 has been insta-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
+ "if-you-see-this-lang-is-broken": "Sentinel language is working!",
+ "no-online-player": "§cYou must provide an online player to send a message to!",
+ "spam-block-warn": "Do not spam in chat! Please wait before sending another message.",
+ "elevating-perms": "Elevating your permissions...",
+ "profanity-block-warn": "§cPlease do not swear in chat! Attempting to bypass this filter will result in a mute! §7§o(Hover for more info)",
+ "spy-disabled": "SocialSpy is now disabled.",
+ "severity-notification-hover": "§8]\u003d\u003d-- §d§lSentinel §8--\u003d\u003d[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§bSeverity: §c%3$s\n§7§o(click to report false positive)",
+ "false-positive-report-success": "Successfully reported a false positive!",
+ "cooldown": "This action is on cooldown!",
+ "spy-message-hover": "§8]\u003d\u003d-- §d§lSocialSpy §8--\u003d\u003d[\n§bSender: §f%1$S\n§bReceiver: §f%2$S\n§bMessage: §f%3$S",
+ "spam-notification": "§b§n%1$s§7 might be spamming! §8(§c%2$s§7/§4%3$s§8)",
+ "unicode-warn": "§cDo not send non-standard unicode in chat!",
+ "slur-mute-warn": "§cYou have been insta-punished by the anti-slur! §7§o(Hover for more info)",
+ "profanity-block-notification": "§b§n%1$s§7 has triggered the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
+ "spy-enabled": "SocialSpy is now enabled.",
+ "message-received": "§d§lMessage §8» §b[§f%1$s §e\u003e§f You§b] §7%2$s",
+ "unicode-notification": "§b§n%1$s§7 has triggered the anti-unicode.",
+ "spam-mute-notification": "§b§n%1$s§7 has been auto-muted by the anti spam! §8(§c%2$s§7/§4%3$s§8)",
+ "no-permission": "§cInsufficient Permissions!",
+ "log-elevating-perms": "Elevating the permissions of %s",
+ "unicode-notification-hover": "§8]\u003d\u003d-- §d§lSentinel §8--\u003d\u003d[\n§bMessage: §f%1$s",
+ "url-notification": "§b§n%1$s§7 has triggered the anti-URL.",
+ "already-op": "You are already a server operator!",
+ "no-trust": "You are not a trusted user!",
+ "action-automatic-reportable": "§7This action was preformed automatically \n§7by the §bSentinel Profanity Filter§7 algorithm!\n§8§o(Click to report false positive)"
+ }
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/main-config.json b/server/plugins/Sentinel/main-config.json
new file mode 100644
index 0000000..2f90c9f
--- /dev/null
+++ b/server/plugins/Sentinel/main-config.json
@@ -0,0 +1,87 @@
+{
+ "plugin": {
+ "license": "null",
+ "prefix": "§d§lSentinel §8» §7",
+ "webhook": "https://discord.com/api/webhooks/id/token",
+ "lang": "en-us.json",
+ "trustedPlayers": [
+ "049460f7-21cb-42f5-8059-d42752bf406f"
+ ],
+ "blockSpecific": true,
+ "preventNBT": true,
+ "preventCmdBlockPlace": true,
+ "preventCmdBlockUse": true,
+ "preventCmdBlockChange": true,
+ "cmdBlockWhitelist": false,
+ "deleteUnauthorizedCmdBlocks": false,
+ "logUnauthorizedCmdBlocks": false,
+ "preventCmdCartPlace": true,
+ "preventCmdCartUse": true,
+ "cmdBlockOpCheck": true,
+ "dangerous": [
+ "op",
+ "deop",
+ "stop",
+ "restart",
+ "execute",
+ "sudo",
+ "esudo",
+ "fill",
+ "setblock",
+ "data",
+ "whitelist"
+ ],
+ "logDangerous": true,
+ "logCmdBlocks": true,
+ "logNBT": true,
+ "logSpecific": false,
+ "logged": [
+ "give",
+ "item"
+ ],
+ "deop": true,
+ "nbtPunish": false,
+ "cmdBlockPunish": false,
+ "commandPunish": false,
+ "specificPunish": false,
+ "punishCommands": [
+ "smite %player%",
+ "ban %player% ]\u003d- Sentinel -\u003d[ You have been banned for attempting a dangerous action. If you believe this to be a mistake, please contact the server owner."
+ ],
+ "reopCommand": false,
+ "pluginHider": true
+ },
+ "chat": {
+ "antiSwear": {
+ "antiSwearEnabled": true,
+ "lowScore": 0,
+ "mediumLowScore": 1,
+ "mediumScore": 3,
+ "mediumHighScore": 5,
+ "highScore": 7,
+ "scoreDecay": 3,
+ "punishScore": 20,
+ "swearPunishCommand": "mute %player% 15m Do not attempt to bypass the Profanity Filter",
+ "strictPunishCommand": "mute %player% 1h Discriminatory speech is not tolerated on this server!",
+ "logSwears": true
+ },
+ "antiSpam": {
+ "antiSpamEnabled": true,
+ "defaultGain": 1,
+ "lowGain": 2,
+ "mediumGain": 4,
+ "highGain": 6,
+ "heatDecay": 1,
+ "blockHeat": 10,
+ "punishHeat": 25,
+ "clearChat": true,
+ "chatClearCommand": "cc",
+ "spamPunishCommand": "mute %player% 1m Please refrain from spamming!",
+ "logSpam": true
+ },
+ "useAntiURL": true,
+ "useSwearRegex": false,
+ "useStrictRegex": false,
+ "useAntiUnicode": true
+ }
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/nbt-config.json b/server/plugins/Sentinel/nbt-config.json
new file mode 100644
index 0000000..7c524bd
--- /dev/null
+++ b/server/plugins/Sentinel/nbt-config.json
@@ -0,0 +1,46 @@
+{
+ "allowName": true,
+ "allowLore": true,
+ "allowAttributes": false,
+ "allowPotions": false,
+ "globalMaxEnchant": 5,
+ "maxMending": 1,
+ "maxUnbreaking": 3,
+ "maxVanishing": 1,
+ "maxAquaAffinity": 1,
+ "maxBlastProtection": 4,
+ "maxCurseOfBinding": 1,
+ "maxDepthStrider": 3,
+ "maxFeatherFalling": 4,
+ "maxFireProtection": 4,
+ "maxFrostWalker": 2,
+ "maxProjectileProtection": 4,
+ "maxProtection": 4,
+ "maxRespiration": 3,
+ "maxSoulSpeed": 3,
+ "maxThorns": 3,
+ "maxSwiftSneak": 3,
+ "maxBaneOfArthropods": 5,
+ "maxEfficiency": 5,
+ "maxFireAspect": 2,
+ "maxLooting": 3,
+ "maxImpaling": 5,
+ "maxKnockback": 2,
+ "maxSharpness": 5,
+ "maxSmite": 5,
+ "maxSweepingEdge": 3,
+ "maxChanneling": 1,
+ "maxFlame": 1,
+ "maxInfinity": 1,
+ "maxLoyalty": 3,
+ "maxRiptide": 3,
+ "maxMultishot": 1,
+ "maxPiercing": 4,
+ "maxPower": 5,
+ "maxPunch": 2,
+ "maxQuickCharge": 3,
+ "maxFortune": 3,
+ "maxLuckOfTheSea": 3,
+ "maxLure": 3,
+ "maxSilkTouch": 1
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/storage/whitelist.json b/server/plugins/Sentinel/storage/whitelist.json
new file mode 100644
index 0000000..a717900
--- /dev/null
+++ b/server/plugins/Sentinel/storage/whitelist.json
@@ -0,0 +1,3 @@
+{
+ "whitelistedCMDBlocks": []
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/strict.json b/server/plugins/Sentinel/strict.json
new file mode 100644
index 0000000..63534c1
--- /dev/null
+++ b/server/plugins/Sentinel/strict.json
@@ -0,0 +1,12 @@
+{
+ "strict": [
+ "nigg",
+ "niger",
+ "nlgg",
+ "nlger",
+ "njgg",
+ "tranny",
+ "fag",
+ "beaner"
+ ]
+}
\ No newline at end of file
diff --git a/server/plugins/Sentinel/swears.json b/server/plugins/Sentinel/swears.json
new file mode 100644
index 0000000..ff7e3e6
--- /dev/null
+++ b/server/plugins/Sentinel/swears.json
@@ -0,0 +1,82 @@
+{
+ "swears": [
+ "anal",
+ "anus",
+ "arse",
+ "ass",
+ "ballsack",
+ "balls",
+ "bastard",
+ "bitch",
+ "btch",
+ "biatch",
+ "blowjob",
+ "bollock",
+ "bollok",
+ "boner",
+ "boob",
+ "bugger",
+ "butt",
+ "choad",
+ "clitoris",
+ "cock",
+ "coon",
+ "crap",
+ "cum",
+ "cunt",
+ "dick",
+ "dildo",
+ "douchebag",
+ "dyke",
+ "feck",
+ "fellate",
+ "fellatio",
+ "felching",
+ "fuck",
+ "fudgepacker",
+ "flange",
+ "gtfo",
+ "hoe",
+ "horny",
+ "incest",
+ "jerk",
+ "jizz",
+ "labia",
+ "masturb",
+ "muff",
+ "nazi",
+ "nipple",
+ "nips",
+ "nude",
+ "pedophile",
+ "penis",
+ "piss",
+ "poop",
+ "porn",
+ "prick",
+ "prostit",
+ "pube",
+ "pussie",
+ "pussy",
+ "queer",
+ "rape",
+ "rapist",
+ "retard",
+ "rimjob",
+ "scrotum",
+ "sex",
+ "shit",
+ "slut",
+ "spunk",
+ "stfu",
+ "suckmy",
+ "tits",
+ "tittie",
+ "titty",
+ "turd",
+ "twat",
+ "vagina",
+ "wank",
+ "whore"
+ ]
+}
\ No newline at end of file
diff --git a/server/plugins/bStats/config.yml b/server/plugins/bStats/config.yml
new file mode 100644
index 0000000..4905acb
--- /dev/null
+++ b/server/plugins/bStats/config.yml
@@ -0,0 +1,8 @@
+# bStats collects some data for plugin authors like how many servers are using their plugins.
+# To honor their work, you should not disable it.
+# This has nearly no effect on the server performance!
+# Check out https://bStats.org/ to learn more :)
+
+enabled: true
+serverUuid: 0fd3d4be-a84f-42dc-a7ce-b62afe45c292
+logFailedRequests: false
diff --git a/server/server.jar b/server/server.jar
new file mode 100644
index 0000000..5b0abcb
Binary files /dev/null and b/server/server.jar differ
diff --git a/server/server.properties b/server/server.properties
new file mode 100644
index 0000000..ed1ec9b
--- /dev/null
+++ b/server/server.properties
@@ -0,0 +1,61 @@
+#Minecraft server properties
+#Wed Feb 21 14:28:28 CST 2024
+enable-jmx-monitoring=false
+rcon.port=25575
+level-seed=
+gamemode=survival
+enable-command-block=true
+enable-query=false
+generator-settings={}
+enforce-secure-profile=false
+level-name=world
+motd=A Minecraft Server
+query.port=25565
+pvp=true
+generate-structures=true
+max-chained-neighbor-updates=1000000
+difficulty=easy
+network-compression-threshold=256
+max-tick-time=60000
+require-resource-pack=false
+use-native-transport=true
+max-players=20
+online-mode=true
+enable-status=true
+allow-flight=false
+initial-disabled-packs=
+broadcast-rcon-to-ops=true
+view-distance=10
+server-ip=
+resource-pack-prompt=
+allow-nether=true
+server-port=25565
+enable-rcon=false
+sync-chunk-writes=true
+resource-pack-id=
+op-permission-level=4
+prevent-proxy-connections=false
+hide-online-players=false
+resource-pack=
+entity-broadcast-range-percentage=100
+simulation-distance=10
+rcon.password=
+player-idle-timeout=0
+debug=false
+force-gamemode=false
+rate-limit=0
+hardcore=false
+white-list=false
+broadcast-console-to-ops=true
+spawn-npcs=true
+spawn-animals=true
+log-ips=true
+function-permission-level=2
+initial-enabled-packs=vanilla
+level-type=minecraft\:normal
+text-filtering-config=
+spawn-monsters=true
+enforce-whitelist=false
+spawn-protection=16
+resource-pack-sha1=
+max-world-size=29999984
diff --git a/server/spigot.yml b/server/spigot.yml
new file mode 100644
index 0000000..66bb2fe
--- /dev/null
+++ b/server/spigot.yml
@@ -0,0 +1,178 @@
+# This is the main configuration file for Spigot.
+# As you can see, there's tons to configure. Some options may impact gameplay, so use
+# with caution, and make sure you know what each option does before configuring.
+# For a reference for any variable inside this file, check out the Spigot wiki at
+# http://www.spigotmc.org/wiki/spigot-configuration/
+#
+# If you need help with the configuration or have any questions related to Spigot,
+# join us at the Discord or drop by our forums and leave a post.
+#
+# Discord: https://www.spigotmc.org/go/discord
+# Forums: http://www.spigotmc.org/
+
+settings:
+ debug: false
+ save-user-cache-on-stop-only: false
+ timeout-time: 60
+ restart-on-crash: true
+ restart-script: ./start.sh
+ sample-count: 12
+ bungeecord: false
+ moved-wrongly-threshold: 0.0625
+ moved-too-quickly-multiplier: 10.0
+ player-shuffle: 0
+ user-cache-size: 1000
+ netty-threads: 4
+ attribute:
+ maxHealth:
+ max: 2048.0
+ movementSpeed:
+ max: 2048.0
+ attackDamage:
+ max: 2048.0
+ log-villager-deaths: true
+ log-named-deaths: true
+messages:
+ whitelist: You are not whitelisted on this server!
+ unknown-command: Unknown command. Type "/help" for help.
+ server-full: The server is full!
+ outdated-client: Outdated client! Please use {0}
+ outdated-server: Outdated server! I'm still on {0}
+ restart: Server is restarting
+advancements:
+ disable-saving: false
+ disabled:
+ - minecraft:story/disabled
+commands:
+ silent-commandblock-console: false
+ replace-commands:
+ - setblock
+ - summon
+ - testforblock
+ - tellraw
+ log: true
+ spam-exclusions:
+ - /skill
+ tab-complete: 0
+ send-namespaced: true
+players:
+ disable-saving: false
+world-settings:
+ default:
+ below-zero-generation-in-existing-chunks: true
+ growth:
+ cactus-modifier: 100
+ cane-modifier: 100
+ melon-modifier: 100
+ mushroom-modifier: 100
+ pumpkin-modifier: 100
+ sapling-modifier: 100
+ beetroot-modifier: 100
+ carrot-modifier: 100
+ potato-modifier: 100
+ torchflower-modifier: 100
+ wheat-modifier: 100
+ netherwart-modifier: 100
+ vine-modifier: 100
+ cocoa-modifier: 100
+ bamboo-modifier: 100
+ sweetberry-modifier: 100
+ kelp-modifier: 100
+ twistingvines-modifier: 100
+ weepingvines-modifier: 100
+ cavevines-modifier: 100
+ glowberry-modifier: 100
+ pitcherplant-modifier: 100
+ entity-activation-range:
+ animals: 32
+ monsters: 32
+ raiders: 48
+ misc: 16
+ water: 16
+ villagers: 32
+ flying-monsters: 32
+ wake-up-inactive:
+ animals-max-per-tick: 4
+ animals-every: 1200
+ animals-for: 100
+ monsters-max-per-tick: 8
+ monsters-every: 400
+ monsters-for: 100
+ villagers-max-per-tick: 4
+ villagers-every: 600
+ villagers-for: 100
+ flying-monsters-max-per-tick: 8
+ flying-monsters-every: 200
+ flying-monsters-for: 100
+ villagers-work-immunity-after: 100
+ villagers-work-immunity-for: 20
+ villagers-active-for-panic: true
+ tick-inactive-villagers: true
+ ignore-spectators: false
+ entity-tracking-range:
+ players: 48
+ animals: 48
+ monsters: 48
+ misc: 32
+ display: 128
+ other: 64
+ ticks-per:
+ hopper-transfer: 8
+ hopper-check: 1
+ hopper-amount: 1
+ hopper-can-load-chunks: false
+ seed-village: 10387312
+ seed-desert: 14357617
+ seed-igloo: 14357618
+ seed-jungle: 14357619
+ seed-swamp: 14357620
+ seed-monument: 10387313
+ seed-shipwreck: 165745295
+ seed-ocean: 14357621
+ seed-outpost: 165745296
+ seed-endcity: 10387313
+ seed-slime: 987234911
+ seed-nether: 30084232
+ seed-mansion: 10387319
+ seed-fossil: 14357921
+ seed-portal: 34222645
+ seed-ancientcity: 20083232
+ seed-trailruins: 83469867
+ seed-trialchambers: 94251327
+ seed-buriedtreasure: 10387320
+ seed-mineshaft: default
+ seed-stronghold: default
+ max-tick-time:
+ tile: 50
+ entity: 50
+ hunger:
+ jump-walk-exhaustion: 0.05
+ jump-sprint-exhaustion: 0.2
+ combat-exhaustion: 0.1
+ regen-exhaustion: 6.0
+ swim-multiplier: 0.01
+ sprint-multiplier: 0.1
+ other-multiplier: 0.0
+ max-tnt-per-tick: 100
+ thunder-chance: 100000
+ view-distance: default
+ simulation-distance: default
+ mob-spawn-range: 8
+ merge-radius:
+ item: 2.5
+ exp: 3.0
+ arrow-despawn-rate: 1200
+ trident-despawn-rate: 1200
+ item-despawn-rate: 6000
+ nerf-spawner-mobs: false
+ dragon-death-sound-radius: 0
+ hanging-tick-frequency: 100
+ zombie-aggressive-towards-villager: true
+ wither-spawn-sound-radius: 0
+ end-portal-sound-radius: 0
+ enable-zombie-pigmen-portal-spawns: true
+ verbose: false
+config-version: 12
+stats:
+ disable-saving: false
+ forced-stats: {}
diff --git a/server/usercache.json b/server/usercache.json
new file mode 100644
index 0000000..c73561d
--- /dev/null
+++ b/server/usercache.json
@@ -0,0 +1 @@
+[{"name":"obvWolf","uuid":"049460f7-21cb-42f5-8059-d42752bf406f","expiresOn":"2024-03-21 14:29:48 -0500"}]
\ No newline at end of file
diff --git a/server/version_history.json b/server/version_history.json
new file mode 100644
index 0000000..33b3537
--- /dev/null
+++ b/server/version_history.json
@@ -0,0 +1 @@
+{"currentVersion":"git-Paper-430 (MC: 1.20.4)"}
\ No newline at end of file
diff --git a/server/versions/1.20.4/paper-1.20.4.jar b/server/versions/1.20.4/paper-1.20.4.jar
new file mode 100644
index 0000000..71921aa
Binary files /dev/null and b/server/versions/1.20.4/paper-1.20.4.jar differ
diff --git a/server/whitelist.json b/server/whitelist.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/server/whitelist.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/server/world/advancements/049460f7-21cb-42f5-8059-d42752bf406f.json b/server/world/advancements/049460f7-21cb-42f5-8059-d42752bf406f.json
new file mode 100644
index 0000000..fd6080c
--- /dev/null
+++ b/server/world/advancements/049460f7-21cb-42f5-8059-d42752bf406f.json
@@ -0,0 +1,15 @@
+{
+ "minecraft:recipes/decorations/crafting_table": {
+ "criteria": {
+ "unlock_right_away": "2024-02-19 14:40:46 -0600"
+ },
+ "done": true
+ },
+ "minecraft:adventure/adventuring_time": {
+ "criteria": {
+ "minecraft:jungle": "2024-02-19 14:40:47 -0600"
+ },
+ "done": false
+ },
+ "DataVersion": 3700
+}
\ No newline at end of file
diff --git a/server/world/data/raids.dat b/server/world/data/raids.dat
new file mode 100644
index 0000000..69ccfde
Binary files /dev/null and b/server/world/data/raids.dat differ
diff --git a/server/world/data/random_sequences.dat b/server/world/data/random_sequences.dat
new file mode 100644
index 0000000..09c92dd
Binary files /dev/null and b/server/world/data/random_sequences.dat differ
diff --git a/server/world/datapacks/bukkit/pack.mcmeta b/server/world/datapacks/bukkit/pack.mcmeta
new file mode 100644
index 0000000..4702dc0
--- /dev/null
+++ b/server/world/datapacks/bukkit/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "description": "Data pack for resources provided by Bukkit plugins",
+ "pack_format": 26
+ }
+}
diff --git a/server/world/entities/r.-1.-1.mca b/server/world/entities/r.-1.-1.mca
new file mode 100644
index 0000000..06cb4fb
Binary files /dev/null and b/server/world/entities/r.-1.-1.mca differ
diff --git a/server/world/entities/r.-1.0.mca b/server/world/entities/r.-1.0.mca
new file mode 100644
index 0000000..4bd2e14
Binary files /dev/null and b/server/world/entities/r.-1.0.mca differ
diff --git a/server/world/entities/r.0.-1.mca b/server/world/entities/r.0.-1.mca
new file mode 100644
index 0000000..7b97f9e
Binary files /dev/null and b/server/world/entities/r.0.-1.mca differ
diff --git a/server/world/entities/r.0.0.mca b/server/world/entities/r.0.0.mca
new file mode 100644
index 0000000..e936133
Binary files /dev/null and b/server/world/entities/r.0.0.mca differ
diff --git a/server/world/level.dat b/server/world/level.dat
new file mode 100644
index 0000000..ae0bf24
Binary files /dev/null and b/server/world/level.dat differ
diff --git a/server/world/level.dat_old b/server/world/level.dat_old
new file mode 100644
index 0000000..142e988
Binary files /dev/null and b/server/world/level.dat_old differ
diff --git a/server/world/paper-world.yml b/server/world/paper-world.yml
new file mode 100644
index 0000000..3fb7f7c
--- /dev/null
+++ b/server/world/paper-world.yml
@@ -0,0 +1,6 @@
+# This is a world configuration file for Paper.
+# This file may start empty but can be filled with settings to override ones in the config/paper-world-defaults.yml
+#
+# World: world (minecraft:overworld)
+
+_version: 30
diff --git a/server/world/playerdata/049460f7-21cb-42f5-8059-d42752bf406f.dat b/server/world/playerdata/049460f7-21cb-42f5-8059-d42752bf406f.dat
new file mode 100644
index 0000000..73abc99
Binary files /dev/null and b/server/world/playerdata/049460f7-21cb-42f5-8059-d42752bf406f.dat differ
diff --git a/server/world/region/r.-1.-1.mca b/server/world/region/r.-1.-1.mca
new file mode 100644
index 0000000..1301321
Binary files /dev/null and b/server/world/region/r.-1.-1.mca differ
diff --git a/server/world/region/r.-1.0.mca b/server/world/region/r.-1.0.mca
new file mode 100644
index 0000000..969fac5
Binary files /dev/null and b/server/world/region/r.-1.0.mca differ
diff --git a/server/world/region/r.0.-1.mca b/server/world/region/r.0.-1.mca
new file mode 100644
index 0000000..a6a3585
Binary files /dev/null and b/server/world/region/r.0.-1.mca differ
diff --git a/server/world/region/r.0.0.mca b/server/world/region/r.0.0.mca
new file mode 100644
index 0000000..a179533
Binary files /dev/null and b/server/world/region/r.0.0.mca differ
diff --git a/server/world/stats/049460f7-21cb-42f5-8059-d42752bf406f.json b/server/world/stats/049460f7-21cb-42f5-8059-d42752bf406f.json
new file mode 100644
index 0000000..cf7cdc5
--- /dev/null
+++ b/server/world/stats/049460f7-21cb-42f5-8059-d42752bf406f.json
@@ -0,0 +1 @@
+{"stats":{"minecraft:picked_up":{"minecraft:lever":1},"minecraft:used":{"minecraft:repeating_command_block":1,"minecraft:lever":2,"minecraft:command_block":2},"minecraft:custom":{"minecraft:jump":55,"minecraft:time_since_rest":47351,"minecraft:play_time":47351,"minecraft:leave_game":7,"minecraft:sprint_one_cm":507,"minecraft:damage_taken":40,"minecraft:time_since_death":47351,"minecraft:walk_one_cm":3818,"minecraft:sneak_time":14,"minecraft:climb_one_cm":692,"minecraft:total_world_time":47351,"minecraft:fly_one_cm":421,"minecraft:fall_one_cm":868}},"DataVersion":3700}
\ No newline at end of file
diff --git a/server/world/uid.dat b/server/world/uid.dat
new file mode 100644
index 0000000..d06ad9c
--- /dev/null
+++ b/server/world/uid.dat
@@ -0,0 +1 @@
+€pD-’*aU–§Û
\ No newline at end of file
diff --git a/server/world_nether/DIM-1/data/raids.dat b/server/world_nether/DIM-1/data/raids.dat
new file mode 100644
index 0000000..69ccfde
Binary files /dev/null and b/server/world_nether/DIM-1/data/raids.dat differ
diff --git a/server/world_nether/DIM-1/entities/r.-1.-1.mca b/server/world_nether/DIM-1/entities/r.-1.-1.mca
new file mode 100644
index 0000000..070b092
Binary files /dev/null and b/server/world_nether/DIM-1/entities/r.-1.-1.mca differ
diff --git a/server/world_nether/DIM-1/entities/r.-1.0.mca b/server/world_nether/DIM-1/entities/r.-1.0.mca
new file mode 100644
index 0000000..ba1872a
Binary files /dev/null and b/server/world_nether/DIM-1/entities/r.-1.0.mca differ
diff --git a/server/world_nether/DIM-1/entities/r.0.-1.mca b/server/world_nether/DIM-1/entities/r.0.-1.mca
new file mode 100644
index 0000000..5641a89
Binary files /dev/null and b/server/world_nether/DIM-1/entities/r.0.-1.mca differ
diff --git a/server/world_nether/DIM-1/entities/r.0.0.mca b/server/world_nether/DIM-1/entities/r.0.0.mca
new file mode 100644
index 0000000..bda350f
Binary files /dev/null and b/server/world_nether/DIM-1/entities/r.0.0.mca differ
diff --git a/server/world_nether/DIM-1/region/r.-1.-1.mca b/server/world_nether/DIM-1/region/r.-1.-1.mca
new file mode 100644
index 0000000..f36ce25
Binary files /dev/null and b/server/world_nether/DIM-1/region/r.-1.-1.mca differ
diff --git a/server/world_nether/DIM-1/region/r.-1.0.mca b/server/world_nether/DIM-1/region/r.-1.0.mca
new file mode 100644
index 0000000..bd460fe
Binary files /dev/null and b/server/world_nether/DIM-1/region/r.-1.0.mca differ
diff --git a/server/world_nether/DIM-1/region/r.0.-1.mca b/server/world_nether/DIM-1/region/r.0.-1.mca
new file mode 100644
index 0000000..b41eb74
Binary files /dev/null and b/server/world_nether/DIM-1/region/r.0.-1.mca differ
diff --git a/server/world_nether/DIM-1/region/r.0.0.mca b/server/world_nether/DIM-1/region/r.0.0.mca
new file mode 100644
index 0000000..e0c79ac
Binary files /dev/null and b/server/world_nether/DIM-1/region/r.0.0.mca differ
diff --git a/server/world_nether/level.dat b/server/world_nether/level.dat
new file mode 100644
index 0000000..f22e517
Binary files /dev/null and b/server/world_nether/level.dat differ
diff --git a/server/world_nether/level.dat_old b/server/world_nether/level.dat_old
new file mode 100644
index 0000000..b60cefd
Binary files /dev/null and b/server/world_nether/level.dat_old differ
diff --git a/server/world_nether/paper-world.yml b/server/world_nether/paper-world.yml
new file mode 100644
index 0000000..3f276e7
--- /dev/null
+++ b/server/world_nether/paper-world.yml
@@ -0,0 +1,6 @@
+# This is a world configuration file for Paper.
+# This file may start empty but can be filled with settings to override ones in the config/paper-world-defaults.yml
+#
+# World: world_nether (minecraft:the_nether)
+
+_version: 30
diff --git a/server/world_nether/uid.dat b/server/world_nether/uid.dat
new file mode 100644
index 0000000..cddd4c1
--- /dev/null
+++ b/server/world_nether/uid.dat
@@ -0,0 +1 @@
+uË;;“L`´(!¬f¶A
\ No newline at end of file
diff --git a/server/world_the_end/DIM1/data/raids_end.dat b/server/world_the_end/DIM1/data/raids_end.dat
new file mode 100644
index 0000000..69ccfde
Binary files /dev/null and b/server/world_the_end/DIM1/data/raids_end.dat differ
diff --git a/server/world_the_end/DIM1/entities/r.-1.-1.mca b/server/world_the_end/DIM1/entities/r.-1.-1.mca
new file mode 100644
index 0000000..78453b9
Binary files /dev/null and b/server/world_the_end/DIM1/entities/r.-1.-1.mca differ
diff --git a/server/world_the_end/DIM1/entities/r.-1.0.mca b/server/world_the_end/DIM1/entities/r.-1.0.mca
new file mode 100644
index 0000000..b29f4fd
Binary files /dev/null and b/server/world_the_end/DIM1/entities/r.-1.0.mca differ
diff --git a/server/world_the_end/DIM1/entities/r.0.-1.mca b/server/world_the_end/DIM1/entities/r.0.-1.mca
new file mode 100644
index 0000000..a273723
Binary files /dev/null and b/server/world_the_end/DIM1/entities/r.0.-1.mca differ
diff --git a/server/world_the_end/DIM1/entities/r.0.0.mca b/server/world_the_end/DIM1/entities/r.0.0.mca
new file mode 100644
index 0000000..f8aa7e0
Binary files /dev/null and b/server/world_the_end/DIM1/entities/r.0.0.mca differ
diff --git a/server/world_the_end/DIM1/region/r.-1.-1.mca b/server/world_the_end/DIM1/region/r.-1.-1.mca
new file mode 100644
index 0000000..07d300e
Binary files /dev/null and b/server/world_the_end/DIM1/region/r.-1.-1.mca differ
diff --git a/server/world_the_end/DIM1/region/r.-1.0.mca b/server/world_the_end/DIM1/region/r.-1.0.mca
new file mode 100644
index 0000000..1eb374f
Binary files /dev/null and b/server/world_the_end/DIM1/region/r.-1.0.mca differ
diff --git a/server/world_the_end/DIM1/region/r.0.-1.mca b/server/world_the_end/DIM1/region/r.0.-1.mca
new file mode 100644
index 0000000..d4303c8
Binary files /dev/null and b/server/world_the_end/DIM1/region/r.0.-1.mca differ
diff --git a/server/world_the_end/DIM1/region/r.0.0.mca b/server/world_the_end/DIM1/region/r.0.0.mca
new file mode 100644
index 0000000..61ee2c7
Binary files /dev/null and b/server/world_the_end/DIM1/region/r.0.0.mca differ
diff --git a/server/world_the_end/level.dat b/server/world_the_end/level.dat
new file mode 100644
index 0000000..6bf2c49
Binary files /dev/null and b/server/world_the_end/level.dat differ
diff --git a/server/world_the_end/level.dat_old b/server/world_the_end/level.dat_old
new file mode 100644
index 0000000..541369b
Binary files /dev/null and b/server/world_the_end/level.dat_old differ
diff --git a/server/world_the_end/paper-world.yml b/server/world_the_end/paper-world.yml
new file mode 100644
index 0000000..adf1f4f
--- /dev/null
+++ b/server/world_the_end/paper-world.yml
@@ -0,0 +1,6 @@
+# This is a world configuration file for Paper.
+# This file may start empty but can be filled with settings to override ones in the config/paper-world-defaults.yml
+#
+# World: world_the_end (minecraft:the_end)
+
+_version: 30
diff --git a/server/world_the_end/uid.dat b/server/world_the_end/uid.dat
new file mode 100644
index 0000000..e380a07
--- /dev/null
+++ b/server/world_the_end/uid.dat
@@ -0,0 +1 @@
+ßWP·B-§RRx·6s
\ No newline at end of file
diff --git a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java
index e91b660..06a302f 100644
--- a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java
+++ b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java
@@ -1,189 +1,138 @@
package io.github.thetrouper.sentinel;
-import io.github.thetrouper.sentinel.auth.Auth;
-import io.github.thetrouper.sentinel.commands.*;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.LanguageFile;
-import io.github.thetrouper.sentinel.events.*;
-import io.github.thetrouper.sentinel.server.functions.AntiSpam;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.ProtocolManager;
+import io.github.itzispyder.pdk.PDK;
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistStorage;
+import io.github.thetrouper.sentinel.data.config.*;
import io.github.thetrouper.sentinel.server.functions.Authenticator;
-import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
+import io.github.thetrouper.sentinel.server.functions.Load;
import io.github.thetrouper.sentinel.server.functions.Telemetry;
-import io.github.thetrouper.sentinel.server.util.JsonSerializable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
+import java.io.File;
import java.util.logging.Logger;
public final class Sentinel extends JavaPlugin {
+
private static Sentinel instance;
- public static LanguageFile dict;
+ private static final File cfgfile = new File("plugins/Sentinel/main-config.json");
+ private static final File nbtcfg = new File("plugins/Sentinel/nbt-config.json");
+ private static final File strctcfg = new File("plugins/Sentinel/strict.json");
+ private static final File swrcfg = new File("plugins/Sentinel/swears.json");
+ private static final File fpcfg = new File("plugins/Sentinel/false-positives.json");
+ private static final File advcfg = new File("plugins/Sentinel/advanced-config.json");
+ private static final File cmdWhitelist = new File("plugins/Sentinel/storage/whitelist.json");
+ 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());
+ public static LanguageFile lang;
+ public static ProtocolManager protocolManager;
public static final PluginManager manager = Bukkit.getPluginManager();
- public static String prefix = "";
- public static String key = "";
+
public static final Logger log = Bukkit.getLogger();
- public static String identifier = "";
public static boolean usesDynamicIP;
+ public static String serverID;
+ public static String license;
+ public static String IP;
+ public static boolean doNoPlugins = false;
+
+ Load load = new Load();
/**
* Plugin startup logic
*/
@Override
public void onEnable() {
+
log.info("\n]======------ Pre-load started! ------======[");
+ PDK.init(this);
instance = this;
+
log.info("Loading Config...");
+
loadConfig();
+
+ log.info("Loading ProtocolLib");
+
+ if (Bukkit.getServer().getPluginManager().isPluginEnabled("ProtocolLib") && mainConfig.plugin.pluginHider) {
+ doNoPlugins = true;
+ protocolManager = ProtocolLibrary.getProtocolManager();
+ } else {
+ doNoPlugins = false;
+ log.warning("Sentinel: ProtocolLib not found. Sentinel will not attempt to hide your plugins.");
+ }
+
+ log.info("Language Status: (%s)".formatted(lang.brokenLang));
+
log.info("Initializing Server ID...");
- String serverID = Authenticator.getServerID();
- identifier = serverID;
- log.info("Pre-load finished!\n]====---- Requesting Authentication (" + dict.get("example-message") + ") ----====[ \n- License Key: " + key + " \n- Server ID: " + serverID);
- String authStatus = "ERROR";
- String authstatus = "ERROR";
- try {
- authStatus = Authenticator.authorize(key, serverID);
- authstatus = Auth.authorize(key,serverID);
+ serverID = Authenticator.getServerID();
- } catch (Exception e) {
- e.printStackTrace();
- log.info("WTFFFF ARE YOU DOING MAN??????");
- getServer().getPluginManager().disablePlugin(this);
- }
- switch (authStatus) {
- case "AUTHORIZED" -> {
- log.info("\n]======----- Auth Success! -----======[");
- startup();
- authstatus = authstatus.replaceAll("ur a skid lmao","get out of here kiddo");
- }
- case "MINEHUT" -> {
- usesDynamicIP = true;
- String minehutStatus = Telemetry.loadTelemetryHook(serverID, key);
- switch (minehutStatus) {
- case "SUCCESS" -> {
- log.info("Dynamic IP auth Success! " + authstatus);
- startup();
- }
- case "FAILURE" -> {
- log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this.");
- getServer().getPluginManager().disablePlugin(this);
- }
- }
- }
- case "INVALID-ID" -> {
- log.info("Authentication Failure, You have not whitelisted this server ID yet.");
- getServer().getPluginManager().disablePlugin(this);
- }
- case "UNREGISTERED" -> {
- log.warning("Authentication Failure, YOU SHALL NOT PASS! License: " + key + " Server ID: " + serverID);
- getServer().getPluginManager().disablePlugin(this);
- }
- case "ERROR" -> {
- log.warning("Hmmmmmm thats not right... License: " + key + " Server ID: " + serverID + "\nPlease report the above stacktrace.");
- getServer().getPluginManager().disablePlugin(this);
- }
- }
- }
+ license = mainConfig.plugin.license;
- public void startup() {
- log.info("\n]======----- Loading Sentinel! -----======[");
- loadConfig();
- // Plugin startup logic
- log.info("Starting Up! (" + getDescription().getVersion() + ")...");
+ log.info("Pre-load finished!\n]====---- Requesting Authentication ----====[ \n- License Key: %s\n- Server ID: %s".formatted(license,serverID));
- // Enable Functions
- AntiSpam.enableAntiSpam();
- ProfanityFilter.enableAntiSwear();
-
- prefix = Config.Plugin.getPrefix();
-
- // Commands -> BE SURE TO REGISTER ANY NEW COMMANDS IN PLUGIN.YML (src/main/java/resources/plugin.yml)!
- new SentinelCommand().register();
- new MessageCommand().register();
- new ReplyCommand().register();
- new ReopCommand().register();
- new SocialSpyCommand().register();
- new ChatClickCallback().register();
-
- // Events
- manager.registerEvents(new CommandEvent(),this);
- manager.registerEvents(new CMDBlockExecute(), this);
- manager.registerEvents(new CMDBlockPlace(), this);
- manager.registerEvents(new CMDBlockUse(), this);
- manager.registerEvents(new CMDMinecartPlace(), this);
- manager.registerEvents(new CMDMinecartUse(), this);
- manager.registerEvents(new NBTEvents(), this);
- manager.registerEvents(new ChatEvent(),this);
-
- // Scheduled timers
- Bukkit.getScheduler().runTaskTimer(this, AntiSpam::decayHeat,0, 20);
- Bukkit.getScheduler().runTaskTimer(this, ProfanityFilter::decayScore,0,1200);
- log.info("Finished!\n" +
- " ____ __ ___ \n" +
- "/\\ _`\\ /\\ \\__ __ /\\_ \\ \n" +
- "\\ \\,\\L\\_\\ __ ___\\ \\ ,_\\/\\_\\ ___ __\\//\\ \\ \n" +
- " \\/_\\__ \\ /'__`\\/' _ `\\ \\ \\/\\/\\ \\ /' _ `\\ /'__`\\\\ \\ \\ \n" +
- " /\\ \\L\\ \\/\\ __//\\ \\/\\ \\ \\ \\_\\ \\ \\/\\ \\/\\ \\/\\ __/ \\_\\ \\_ \n" +
- " \\ `\\____\\ \\____\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\_\\ \\____\\/\\____\\\n" +
- " \\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/\n" +
- " ]====---- Advanced Anti-Grief & Chat Filter ----====[");
+ load.load(license,serverID);
}
public void loadConfig() {
+
// Init
- Config.loadConfiguration();
+ 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());
- log.info("Loading Dictionary (" + Config.lang + ")...");
- dict = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile());
- log.info("Verifying Config...");
- getConfig().options().copyDefaults();
- saveDefaultConfig();
+ // Save
+ mainConfig.save();
+ advConfig.save();
+ fpConfig.save();
+ strictConfig.save();
+ swearConfig.save();
+ nbtConfig.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();
}
+
/**
* Plugin shutdown logic
*/
@Override
public void onDisable() {
// Plugin shutdown logic
- log.info("Sentinel has disabled! (" + getDescription().getVersion() + ") Your server is now no longer protected!");
+ log.info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion()));
if (usesDynamicIP) {
- Telemetry.sendShutdownLog(identifier,key);
+ Telemetry.sendShutdownLog();
}
}
- /**
- * Checks if a player is trusted.
- * @param player the player to check
- * @return true if the player is trusted, false otherwise
- */
public static boolean isTrusted(Player player) {
- return Config.trustedPlayers.contains(player.getUniqueId().toString());
+ return Sentinel.mainConfig.plugin.trustedPlayers.contains(player.getUniqueId().toString());
}
- /**
- * Checks if a command is a logged command.
- * @param command the command to check
- * @return true if the command is logged, false otherwise
- */
- public static boolean isLoggedCommand(String command) {
- return Config.logged.contains(command);
+ public static boolean isTrusted(String uuid) {
+ return Sentinel.mainConfig.plugin.trustedPlayers.contains(uuid);
}
- /**
- * Checks if a command is dangerous.
- * @param command the command to check
- * @return true if the command is dangerous, false otherwise
- */
- public static boolean isDangerousCommand(String command) {
- return Config.dangerous.contains(command);
- }
- /**
- * Returns an instance of this plugin
- * @return an instance of this plugin
- */
public static Sentinel getInstance() {
return instance;
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java b/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java
index 8c5bcb7..61b29e9 100644
--- a/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java
+++ b/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java
@@ -20,7 +20,7 @@ final
String
ENCRYPTION_KEY
=
-"If I am reading this and I am not a verified developer for Sentinel AntiNuke, I solely swear that my attempts to de-obfuscate this plugin are purely for virus investigation, and have malicious intentions such as cracking, leaking, or ratting this plugin.";
+"If I am reading this and I am not a verified developer for Sentinel AntiNuke, I solely swear that my attempts to de-obfuscate this plugin are purely for investigation, and have no malicious intentions such as cracking, leaking, or ratting this plugin.";
private
static
final
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java
new file mode 100644
index 0000000..74b0ea1
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java
@@ -0,0 +1,47 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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 io.github.itzispyder.pdk.utils.misc.Cooldown;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.Report;
+import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+
+@CommandRegistry(value = "sentinelcallback", permission = @Permission("sentinel.callbacks"), printStackTrace = true)
+public class ChatClickCallback implements CustomCommand {
+ Cooldown fpReportCooldown = new Cooldown<>();
+ @Override
+ public void dispatchCommand(CommandSender sender, Args args) {
+ Player p = (Player) sender;
+ switch (args.get(0).toString()) {
+ case "fpreport" -> {
+ if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) {
+ p.sendMessage(Text.prefix(Sentinel.lang.cooldown.onCooldown + fpReportCooldown.getCooldown(p.getUniqueId())));
+ } else {
+ long id = args.get(1).toLong();
+ Report send = ReportFalsePositives.reports.get(id);
+ if (send == null) {
+ p.sendMessage(Text.prefix(Sentinel.lang.reports.noReport));
+ return;
+ }
+ p.sendMessage(Text.prefix(Sentinel.lang.reports.reportingFalsePositive));
+ ReportFalsePositives.sendFalsePositiveReport(send);
+ p.sendMessage(Text.prefix(Sentinel.lang.reports.falsePositiveSuccess));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder b) {
+ b.then(b.arg("a_you","b_must","c_be","d_called","e_before","f_running","g_a","h_callback"));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java
new file mode 100644
index 0000000..d55d346
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java
@@ -0,0 +1,45 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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 io.github.itzispyder.pdk.utils.ArrayUtils;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.functions.Message;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+@CommandRegistry(value = "sentinelmessage",permission = @Permission("sentinel.message"))
+public class MessageCommand implements CustomCommand {
+ @Override
+ public void dispatchCommand(CommandSender sender, Args args) {
+ Player p = (Player) sender;
+ Player r = null;
+ if (args.getSize() == 0) {
+ p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noOnlinePlayer));
+ return;
+ }
+ if (args.getSize() == 1) {
+ p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noMessageProvided));
+ return;
+ }
+ r = Bukkit.getPlayer(args.get(0).toString());
+
+ String msg = args.getAll(1).toString().trim();
+
+ if (p.hasPermission("sentinel.message") && r != null) {
+ Message.messagePlayer(p,r,msg);
+ } else if (r == null) p.sendMessage(Text.prefix((Sentinel.lang.playerInteraction.noOnlinePlayer)));
+ else sender.sendMessage(Text.prefix(Sentinel.lang.permissions.noPermission));
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder b) {
+ b.then(b.arg(ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName))
+ .then(b.arg("[]")));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java
new file mode 100644
index 0000000..2fbc7f4
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java
@@ -0,0 +1,36 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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.completions.CompletionBuilder;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+@CommandRegistry(value = "reop")
+public class ReopCommand implements CustomCommand {
+ @Override
+ public void dispatchCommand(CommandSender sender, Args args) {
+ Player p = (Player) sender;
+ if (Sentinel.isTrusted(p) && Sentinel.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.setOp(true);
+ } else {
+ p.sendMessage(Text.prefix(Sentinel.lang.permissions.alreadyOp));
+ Sentinel.log.info(Sentinel.lang.permissions.logAlreadyOp.formatted(p.getName()));
+ p.setOp(true);
+ }
+ } else {
+ p.sendMessage(Text.prefix(Sentinel.lang.permissions.noTrust));
+ }
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder completionBuilder) {
+
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java
new file mode 100644
index 0000000..a561f50
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java
@@ -0,0 +1,46 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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 io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.functions.Message;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.Map;
+import java.util.UUID;
+
+@CommandRegistry(value = "reply", permission = @Permission("sentinel.reply"))
+public class ReplyCommand implements CustomCommand {
+ public static Map replyMap = Message.replyMap;
+ @Override
+ public void dispatchCommand(CommandSender sender, Args args) {
+ String name = sender.getName();
+ Player p = sender.getServer().getPlayer(name);
+ UUID senderID = p.getUniqueId();
+ if (replyMap.get(senderID) == null) {
+ p.sendMessage(Text.prefix(Sentinel.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));
+ }
+ String msg = args.getAll().toString();
+ if (p.hasPermission("sentinel.message")) {
+ Message.messagePlayer(p,r,msg);
+ replyMap.put(senderID,reciverID);
+ } else {
+ sender.sendMessage(Text.prefix(Sentinel.lang.permissions.noPermission));
+ }
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder b) {
+ b.then(b.arg("[]"));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java
new file mode 100644
index 0000000..46eed46
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java
@@ -0,0 +1,176 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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 io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
+import io.github.thetrouper.sentinel.server.functions.*;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.CommandBlock;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+@CommandRegistry(value = "sentinel",printStackTrace = true)
+public class SentinelCommand implements CustomCommand {
+ public static boolean debugMode;
+ public static List autoWhitelist = new ArrayList<>();
+
+ @Override
+ public void dispatchCommand(CommandSender commandSender, Args args) {
+ Sentinel instance = Sentinel.getInstance();
+ if (Load.lite) {
+ commandSender.sendMessage(Text.color("""
+ &8]=-&f Welcome to &d&lSentinel &7|&f Anti-Nuke &8-=[
+ &7The plugin is currently loaded in &clite&7 mode.
+
+ &fIf you have just &apurchased&f the plugin:
+ &8- &7Join the &b&ndiscord&r&7 and open a ticket.
+ &8- &7https://discord.gg/Xh6BAzNtxY
+ &8- &7You will then receive a license key.
+ &fIf you have &cnot&f purchased the plugin:
+ &8- &7Then purchase it :D
+ &8- &7It wont do anything in this state!
+ &8- &7(Its only 5$)
+ &fIf you are reading this from a decompiler:
+ &8- &7Please stop trying to crack the plugin and purchase it!
+ &8- &7Your time spent trying trying to bypass my DRM could be spent at a minimum wage job.
+ &8- &7There you will make 7$ an hour! (As oppose to 5$ for multiple hours of cracking)
+ &fWoah! You read quite far!
+ &8- &7Want the plugin for cheaper, &nor even for free&r&7?
+ &8- &7DM &b@obvwolf&7 on discord and lets make a deal!
+ """));
+ return;
+ }
+ Player p = (Player) commandSender;
+ if (!p.hasPermission("sentinel.staff")) return;
+ switch (args.get(0).toString()) {
+ case "commandblock", "cb" -> handleCommandBlock(p,args);
+ case "reload" -> {
+ if (!Sentinel.isTrusted(p)) return;
+ p.sendMessage(Text.prefix("Reloading Sentinel!"));
+ Sentinel.log.info("[Sentinel] Re-Initializing Sentinel!");
+ instance.loadConfig();
+ }
+ case "full-system-check" -> {
+ if (!Sentinel.isTrusted(p)) return;
+ p.sendMessage(Text.prefix("Initiating a full system check!"));
+ SystemCheck.fullCheck(p);
+ }
+ case "debug" -> handleDebugCommand(p,args);
+ case "false-positive" -> handleFalsePositive(p,args);
+ }
+ }
+ private void handleFalsePositive(Player p, Args args) {
+ String falsePositive = args.getAll(2).toString();
+ switch (args.get(1).toString()) {
+ case "add" -> {
+ Sentinel.fpConfig.swearWhitelist.add(falsePositive);
+ p.sendMessage(Text.prefix("&7Successfully added &a%s&7 to the false positive list!".formatted(falsePositive)));
+ }
+ case "remove" -> {
+ Sentinel.fpConfig.swearWhitelist.remove(falsePositive);
+ p.sendMessage(Text.prefix("&7Successfully removed &c%s&7 to the false positive list!".formatted(falsePositive)));
+ }
+ }
+ Sentinel.fpConfig.save();
+ }
+ private void handleCommandBlock(Player p, Args args) {
+ if (!Sentinel.isTrusted(p)) return;
+ Block target = p.getTargetBlock(Set.of(Material.AIR),10);
+ switch (args.get(1).toString()) {
+ case "add" -> {
+ if (target.getType().equals(Material.COMMAND_BLOCK) || target.getType().equals(Material.REPEATING_COMMAND_BLOCK) || target.getType().equals(Material.CHAIN_COMMAND_BLOCK)) {
+ CommandBlock cb = (CommandBlock) target.getState();
+ CMDBlockWhitelist.add(cb,p.getUniqueId());
+ return;
+ }
+ p.sendMessage(Text.prefix("Could not whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it is not a command block!"));
+ }
+ case "remove" -> {
+ WhitelistedBlock wb = CMDBlockWhitelist.get(target.getLocation());
+ if (wb != null) {
+ CMDBlockWhitelist.remove(target.getLocation());
+ p.sendMessage(Text.prefix("Successfully removed 1 &b" + Text.cleanName(WhitelistedBlock.fromSerialized(wb.loc()).getBlock().getType().toString()) + "&7 with the command &a" + wb.command() + "&7."));
+ return;
+ }
+ p.sendMessage(Text.prefix("Could not un-whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it wasn't whitelisted in the first place!"));
+ }
+ case "auto" -> {
+ if (autoWhitelist.contains(p.getUniqueId())) {
+ autoWhitelist.remove(p.getUniqueId());
+ p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 off for you."));
+ } else {
+ autoWhitelist.add(p.getUniqueId());
+ p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 on for you."));
+ }
+ }
+ case "restore" -> {
+ if (args.get(2).toString().equals("all")) {
+ int result = CMDBlockWhitelist.restoreAll();
+ p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks.".formatted(result)));
+ return;
+ }
+ String who = args.get(2).toString();
+ UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
+ int result = CMDBlockWhitelist.restoreAll(id);
+ p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
+ }
+ case "clear" -> {
+ if (args.get(2).toString().equals("all")) {
+ int result = CMDBlockWhitelist.clearAll();
+ p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks.".formatted(result)));
+ return;
+ }
+ String who = args.get(2).toString();
+ UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
+ int result = CMDBlockWhitelist.clearAll(id);
+ p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
+ }
+ }
+ }
+
+ private void handleDebugCommand(Player p, Args args) {
+ if (!p.hasPermission("sentinel.debug")) return;
+ switch (args.get(1).toString()) {
+ case "lang" -> {
+ p.sendMessage(Sentinel.lang.brokenLang);
+ }
+ case "toggle" -> {
+ debugMode = !debugMode;
+ p.sendMessage(Text.prefix((debugMode ? "Enabled" : "Disabled") + " debug mode."));
+ }
+ case "chat" -> {
+ AsyncPlayerChatEvent message = new AsyncPlayerChatEvent(true,p,args.getAll(2).toString(), Set.of(p));
+ AdvancedBlockers.handleAdvanced(message, ReportFalsePositives.initializeReport(message));
+ AntiSpam.handleAntiSpam(message,ReportFalsePositives.initializeReport(message));
+ ProfanityFilter.handleProfanityFilter(message,ReportFalsePositives.initializeReport(message));
+ if (!message.isCancelled()) p.sendMessage(Text.prefix("Message did not get flagged."));
+ }
+ }
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder b) {
+ b.then(b.arg("reload","full-system-check"));
+ 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").then(b.arg("add","remove","auto"))
+ .then(b.arg("restore")
+ .then(b.arg("","all")))
+ .then(b.arg("clear")
+ .then(b.arg("","all"))));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java
new file mode 100644
index 0000000..fb26b82
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java
@@ -0,0 +1,39 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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 io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+@CommandRegistry(value = "socialspy", permission = @Permission("sentinel.spy"))
+public class SocialSpyCommand implements CustomCommand {
+
+ public static Map spyMap = new HashMap<>();
+ @Override
+ public void dispatchCommand(CommandSender sender, Args args) {
+ String name = sender.getName();
+ Player p = sender.getServer().getPlayer(name);
+ UUID senderID = p.getUniqueId();
+ if (!spyMap.containsKey(senderID) || !spyMap.get(senderID)) {
+ sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.enabled));
+ spyMap.put(senderID,true);
+ } else if (spyMap.get(senderID)) {
+ sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.disabled));
+ spyMap.put(senderID,false);
+ }
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder completionBuilder) {
+
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/TrapCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/TrapCommand.java
new file mode 100644
index 0000000..d6cbce8
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/cmds/TrapCommand.java
@@ -0,0 +1,24 @@
+package io.github.thetrouper.sentinel.cmds;
+
+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.completions.CompletionBuilder;
+import io.github.thetrouper.sentinel.Sentinel;
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+
+@CommandRegistry(value = "sentineltab")
+public class TrapCommand implements CustomCommand {
+ private final List fakePlugins = Sentinel.advConfig.fakePlugins;
+ @Override
+ public void dispatchCommand(CommandSender commandSender, Args args) {
+
+ }
+
+ @Override
+ public void dispatchCompletions(CompletionBuilder b) {
+ b.then(b.arg(fakePlugins));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java b/src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java
deleted file mode 100644
index 272fb9a..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :)
- */
-
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
-import io.github.thetrouper.sentinel.server.util.Cooldown;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.UUID;
-
-/**
- * Example command
- */
-public class ChatClickCallback extends CustomCommand {
- public static Cooldown fpReportCooldown = new Cooldown<>();
- public ChatClickCallback() {
- super("sentinelcallback");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- Player p = (Player) sender;
- switch (args[0]) {
- case "fpreport" -> {
- if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("cooldown") + fpReportCooldown.getCooldown(p.getUniqueId())));
- } else {
- ReportFalsePositives.sendFalsePositiveReport(args[1]);
- p.sendMessage(Text.prefix(Sentinel.dict.get("false-positive-report-success")));
- }
- }
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
- builder.addCompletion(1,"a_you","b_must","c_be","d_called","e_before","f_running","g_a","h_callback");
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java
deleted file mode 100644
index 6bb43ab..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabExecutor;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-public abstract class CustomCommand implements TabExecutor {
-
- protected static final Sentinel system = Sentinel.getInstance();
- private final String name;
- private boolean printStacktrace;
-
- public CustomCommand(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setPrintStacktrace(boolean printStacktrace) {
- this.printStacktrace = printStacktrace;
- }
-
- public boolean canPrintStacktrace() {
- return printStacktrace;
- }
-
- public abstract void dispatchCommand(CommandSender sender, Command command, String label, String[] args);
- public abstract void registerCompletions(CompletionBuilder builder);
-
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- try {
- dispatchCommand(sender, command, label, args);
- }
- catch (Exception ex) {
- String msg = ex.getMessage();
-
- if (ex instanceof IndexOutOfBoundsException)
- msg = "command incomplete";
- else if (ex instanceof NullPointerException)
- msg = "command contains a null value";
-
- sender.sendMessage(Text.prefix("\u00a74Command Error: \u00a7cUnknown or incomplete command!"));
- sender.sendMessage(Text.prefix("\u00a7cCaused by: \u00a78\u00a7o(" + ex.getClass().getSimpleName() + ") \u00a77" + msg));
- sender.sendMessage(Text.prefix("\u00a7cCorrect Usage: \u00a77" + command.getUsage()));
-
- if (printStacktrace) {
- ex.printStackTrace();
- }
- }
- return true;
- }
-
- @Override
- public List onTabComplete(CommandSender sender, Command command, String label, String[] args) {
- CompletionBuilder builder = new CompletionBuilder(sender, command, label, args);
- registerCompletions(builder);
- return builder.build();
- }
-
- public CustomCommand register() {
- return register(this);
- }
-
- public static CustomCommand register(CustomCommand command) {
- system.getCommand(command.name).setExecutor(command);
- system.getCommand(command.name).setTabCompleter(command);
- return command;
- }
-
- public static class CompletionBuilder {
-
- public final CommandSender sender;
- public final Command command;
- public final String label;
- public final String[] args;
- private final Map> entries;
-
- public CompletionBuilder(CommandSender sender, Command command, String label, String[] args) {
- this.sender = sender;
- this.command = command;
- this.label = label;
- this.args = args;
- this.entries = new HashMap<>();
- }
-
- public CompletionBuilder addCompletion(int index, Predicate condition, Iterable args) {
- addCompletion(index, condition.test(this), args);
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, Predicate condition, String... args) {
- addCompletion(index, condition.test(this), args);
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, Predicate condition, List args) {
- addCompletion(index, condition.test(this), args);
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, boolean condition, Iterable args) {
- if (condition) {
- addCompletion(index, args);
- }
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, boolean condition, String... args) {
- if (condition) {
- addCompletion(index, args);
- }
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, boolean condition, List args) {
- if (condition) {
- addCompletion(index, args);
- }
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, Iterable args) {
- List list = new ArrayList<>();
- args.forEach(list::add);
- addCompletion(index, list);
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, String... args) {
- addCompletion(index, Arrays.asList(args));
- return this;
- }
-
- public CompletionBuilder addCompletion(int index, List args) {
- entries.put(index, args);
- return this;
- }
-
- public void removeCompletion(int index) {
- entries.remove(index);
- }
-
- public List convertLists(Collection input, Function conversion) {
- List list = new ArrayList<>();
- for (I i : input) {
- list.add(conversion.apply(i));
- }
- return list;
- }
-
- public List build() {
- return entries.getOrDefault(args.length, new ArrayList<>()).stream()
- .filter(s -> s.toLowerCase().contains(args[args.length - 1].toLowerCase()))
- .toList();
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java
deleted file mode 100644
index 0395c0c..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.functions.Message;
-import io.github.thetrouper.sentinel.server.util.ArrayUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-public class MessageCommand extends CustomCommand {
- public static Map replyMap = new HashMap<>();
-
- public MessageCommand() {
- super("msg");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- Player p = (Player) sender;
- Player r = null;
- if (args.length == 0) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("no-online-player")));
- }
- if (args.length == 1) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("no-message-provided")));
- }
- r = Bukkit.getPlayer(args[0]);
- String msg = "";
- for (int i = 1; i < args.length; i++) {
- msg = msg.concat(" " + args[i]);
- }
- msg = msg.trim();
- if (p.hasPermission("sentinel.message") && r != null) {
- Message.messagePlayer(p,r,msg);
- } else if (r == null) {
- p.sendMessage(Text.prefix((Sentinel.dict.get("no-online-player"))));
- }
- else {
- sender.sendMessage(Text.prefix(Sentinel.dict.get("no-permission")));
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
- builder.addCompletion(1, ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName));
- builder.addCompletion(2,builder.args.length >= 2, "[]");
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java
deleted file mode 100644
index a01d44e..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-public class ReopCommand extends CustomCommand {
- public ReopCommand() {
- super("reop");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- Player p = (Player) sender;
- if (Sentinel.isTrusted(p)) {
- if (!p.isOp()) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("elevating-perms")));
- Sentinel.log.info(Sentinel.dict.get("log-elevating-perms").formatted(p.getName()));
- p.setOp(true);
- } else {
- p.sendMessage(Text.prefix(Sentinel.dict.get("already-op")));
- Sentinel.log.info(Sentinel.dict.get("log-already-op").formatted(p.getName()));
- p.setOp(true);
- }
- } else {
- p.sendMessage(Text.prefix(Sentinel.dict.get("no-trust")));
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
-
- }
-
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java
deleted file mode 100644
index d504ec8..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.functions.Message;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.UUID;
-
-public class ReplyCommand extends CustomCommand {
- public static Map replyMap = MessageCommand.replyMap;
-
- public ReplyCommand() {
- super("reply");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- String name = sender.getName();
- Player p = sender.getServer().getPlayer(name);
- UUID senderID = p.getUniqueId();
- if (replyMap.get(senderID) == null) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("no-user-reply")));
- }
- Player r = sender.getServer().getPlayer(replyMap.get(senderID));
- UUID reciverID = r.getUniqueId();
- if (args[0] == null) {
- p.sendMessage(Text.prefix(Sentinel.dict.get("no-message-provided")));
- }
- String msg = String.join(" ", Arrays.asList(args));
- if (p.hasPermission("sentinel.message")) {
- Message.messagePlayer(p,r,msg);
- replyMap.put(senderID,reciverID);
- } else {
- sender.sendMessage(Text.prefix(Sentinel.dict.get("no-permission")));
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
- builder.addCompletion(1,builder.args.length >= 2, "[]");
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java
deleted file mode 100644
index 42f56aa..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :)
- */
-
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.server.functions.AntiSpam;
-import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
-import io.github.thetrouper.sentinel.server.util.ArrayUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.AsyncPlayerChatEvent;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Example command
- */
-public class SentinelCommand extends CustomCommand {
- public static boolean debugmode;
-
- public SentinelCommand() {
- super("sentinel");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- Player p = (Player) sender;
- Sentinel instance = Sentinel.getInstance();
- switch (args[0]) {
- case "reload" -> {
- if (!Sentinel.isTrusted(p)) return;
- p.sendMessage(Text.prefix("Reloading Sentinel!"));
- Sentinel.log.info("[Sentinel] Re-Initializing Sentinel!");
- instance.loadConfig();
- }
- case "debug" -> {
- switch (args[1]) {
- case "antiswear" -> {
- HashSet players = new HashSet<>();
- players.add((Player) sender);
- String msg = "";
- for (int i = 1; i < args.length; i++) {
- msg = msg.concat(" " + args[i]);
- }
- msg = msg.trim();
- AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, (Player) sender, msg, players);
- ProfanityFilter.handleProfanityFilter(e);
- }
- case "antispam" -> {
- HashSet players = new HashSet<>();
- players.add((Player) sender);
- String msg = "";
- for (int i = 1; i < args.length; i++) {
- msg = msg.concat(" " + args[i]);
- }
- msg = msg.trim();
- AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, (Player) sender, msg, players);
- AntiSpam.handleAntiSpam(e);
- }
- case "lang" -> {
- p.sendMessage(Sentinel.dict.get("exmaple-message"));
- }
- case "toggle" -> {
- debugmode = !debugmode;
- p.sendMessage(Text.prefix((debugmode ? "enabled" : "disabled") + " debug mode."));
- }
- }
- }
- case "getHeat" -> {
- Player target = Bukkit.getPlayer(args[1]);
- if (target == null) {
- p.sendMessage(Text.prefix("Invalid Player!"));
- return;
- }
- p.sendMessage(Text.prefix("Heat of " + target.getName() + ": &8(&c" + AntiSpam.heatMap.get(target) + "&7/&4" + Config.punishHeat + "&8)"));
- }
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
- builder.addCompletion(1, "debug",
- "getHeat",
- "reload");
- if (builder.args.length >= 2 && builder.args[1].equals("debug")) {
- builder.addCompletion(2, "antiswear",
- "antispam",
- "lang",
- "toggle");
- //builder.addCompletion(2, (builder.args.length >= 1 && builder.args[1].equals("getHeat")), ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName));
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java
deleted file mode 100644
index 55b18dc..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.github.thetrouper.sentinel.commands;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-public class SocialSpyCommand extends CustomCommand {
- public static Map spyMap = new HashMap<>();
-
- public SocialSpyCommand() {
- super("socialspy");
- this.setPrintStacktrace(true);
- }
-
- @Override
- public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) {
- String name = sender.getName();
- Player p = sender.getServer().getPlayer(name);
- UUID senderID = p.getUniqueId();
- if (!spyMap.containsKey(senderID) || !spyMap.get(senderID)) {
- sender.sendMessage(Text.prefix(Sentinel.dict.get("spy-enabled")));
- spyMap.put(senderID,true);
- } else if (spyMap.get(senderID)) {
- sender.sendMessage(Text.prefix(Sentinel.dict.get("spy-disabled")));
- spyMap.put(senderID,false);
- }
- }
-
- @Override
- public void registerCompletions(CompletionBuilder builder) {
-
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/ActionResult.java b/src/main/java/io/github/thetrouper/sentinel/data/ActionResult.java
new file mode 100644
index 0000000..d487ba4
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/ActionResult.java
@@ -0,0 +1,10 @@
+package io.github.thetrouper.sentinel.data;
+
+import org.bukkit.event.Cancellable;
+
+
+import java.util.function.Consumer;
+
+public record ActionResult(String name, Runnable action, boolean isRan) {
+
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java b/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java
index 16bd7c4..dad12a1 100644
--- a/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java
+++ b/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java
@@ -1,24 +1,23 @@
package io.github.thetrouper.sentinel.data;
-import java.awt.*;
-
public enum ActionType {
- SPECIFIC_COMMAND("Anti-Specific has been triggered","The use of a specific command has been detected!", Color.green),
- LOGGED_COMMAND("General command log","A logged command has been executed.", Color.green),
- DANGEROUS_COMMAND("Anti-Nuke has been triggered","The use of a dangerous command has been detected!", Color.red),
- NBT("Anti-NBT has been triggered", "An NBT item has been caught!", Color.orange),
- PLACE_COMMAND_BLOCK("Anti-Nuke has been triggered","The placing of a command block has been detected!", Color.orange),
- USE_COMMAND_BLOCK("Anti-Nuke has been triggered","The use of a command block has been detected!", Color.red),
- UPDATE_COMMAND_BLOCK("HoneyPot log","Caught a command block command!", Color.yellow),
- PLACE_MINECART_COMMAND("Anti-Nuke has been triggered","The placing of a minecart command has been detected!", Color.red),
- USE_MINECART_COMMAND("Anti-Nuke has been triggered", "The use of a command block has been detected!", Color.red),
- UPDATE_MINECART_COMMAND("HoneyPot log","Caught a command block command!", Color.orange);
+ SPECIFIC_COMMAND("Anti-Specific has been triggered","The use of a specific command has been detected!", 0x00FF00),
+ LOGGED_COMMAND("General command log","A logged command has been executed.", 0x00FF00),
+ DANGEROUS_COMMAND("Anti-Nuke has been triggered","The use of a dangerous command has been detected!", 0xFF0000),
+ NBT("Anti-NBT has been triggered", "An NBT item has been caught!", 0xFFB000),
+ PLACE_COMMAND_BLOCK("Anti-Nuke has been triggered","The placing of a command block has been detected!", 0xFFB000),
+ USE_COMMAND_BLOCK("Anti-Nuke has been triggered","The use of a command block has been detected!", 0xFF0000),
+ UPDATE_COMMAND_BLOCK("HoneyPot log","Caught a command block command!", 0xF8FF00),
+ PLACE_MINECART_COMMAND("Anti-Nuke has been triggered","The placing of a minecart command has been detected!", 0xFF0000),
+ USE_MINECART_COMMAND("Anti-Nuke has been triggered", "The use of a command block has been detected!", 0xFF0000),
+ UPDATE_MINECART_COMMAND("HoneyPot has been triggered","Caught a command minecart command!", 0xFFB000),
+ COMMAND_BLOCK_EXECUTE("Command block whitelist has been triggered","Caught an invalid command block.", 0xFFB000);
private final String messageTop;
private final String messageTitle;
- private final Color embedColor;
+ private final int embedColor;
- ActionType(String messagetop, String messageTitle, Color embedColor) {
- this.messageTop = messagetop;
+ ActionType(String messageTop, String messageTitle, int embedColor) {
+ this.messageTop = messageTop;
this.messageTitle = messageTitle;
this.embedColor = embedColor;
}
@@ -28,7 +27,7 @@ public enum ActionType {
public String getMessageTitle() {
return messageTitle;
}
- public Color getEmbedColor() {
+ public int getEmbedColor() {
return embedColor;
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Config.java b/src/main/java/io/github/thetrouper/sentinel/data/Config.java
deleted file mode 100644
index f2b9850..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/data/Config.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :)
- */
-
-package io.github.thetrouper.sentinel.data;
-
-import com.google.common.base.Charsets;
-import io.github.thetrouper.sentinel.Sentinel;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Config loader
- */
-public abstract class Config {
-
- private static final FileConfiguration mainConfig = Sentinel.getInstance().getConfig();
- private static final FileConfiguration nbtConfig = getConfig("nbt-config.yml");
- private static final FileConfiguration falsePositives = getConfig("false-positives.yml");
- private static final FileConfiguration strictWords = getConfig("strict.yml");
- private static final FileConfiguration swearWords = getConfig("swears.yml");
-
- public static List getPunishCommands() {
- return punishCommands;
- }
-
- /**
- * Config plugin section
- */
- public class Plugin {
- public static String getPrefix() {
- return mainConfig.getString("config.plugin.prefix");
- }
- }
- public static String webhook;
- public static String lang;
- public static List trustedPlayers;
- public static boolean blockSpecific;
- public static boolean preventNBT;
- public static boolean preventCmdBlockPlace;
- public static boolean preventCmdBlockUse;
- public static boolean preventCmdBlockChange;
- public static boolean preventCmdCartPlace;
- public static boolean preventCmdCartUse;
- public static boolean cmdBlockOpCheck;
- public static List dangerous;
- public static boolean logDangerous;
- public static boolean logCmdBlocks;
- public static boolean logNBT;
- public static boolean logSpecific;
- public static List logged;
- public static boolean deop;
- public static boolean nbtPunish;
- public static boolean cmdBlockPunish;
- public static boolean commandPunish;
- public static boolean specificPunish;
- public static List punishCommands;
- public static boolean reopCommand;
-
- // NBT
-
- public static boolean allowName;
- public static boolean allowLore;
- public static boolean allowAttributes;
- public static int globalMaxEnchant;
- public static int maxMending;
- public static int maxUnbreaking;
- public static int maxVanishing;
- public static int maxAquaAffinity;
- public static int maxBlastProtection;
- public static int maxCurseOfBinding;
- public static int maxDepthStrider;
- public static int maxFeatherFalling;
- public static int maxFireProtection;
- public static int maxFrostWalker;
- public static int maxProjectileProtection;
- public static int maxProtection;
- public static int maxRespiration;
- public static int maxSoulSpeed;
- public static int maxThorns;
- public static int maxSwiftSneak;
- public static int maxBaneOfArthropods;
- public static int maxEfficiency;
- public static int maxFireAspect;
- public static int maxLooting;
- public static int maxImpaling;
- public static int maxKnockback;
- public static int maxSharpness;
- public static int maxSmite;
- public static int maxSweepingEdge;
- public static int maxChanneling;
- public static int maxFlame;
- public static int maxInfinity;
- public static int maxLoyalty;
- public static int maxRiptide;
- public static int maxMultishot;
- public static int maxPiercing;
- public static int maxPower;
- public static int maxPunch;
- public static int maxQuickCharge;
- public static int maxFortune;
- public static int maxLuckOfTheSea;
- public static int maxLure;
- public static int maxSilkTouch;
-
- // Chat Filter Setup & AntiSpam
- public static boolean antiUnicode;
- public static boolean antiSpamEnabled;
- public static int defaultGain;
- public static int lowGain;
- public static int mediumGain;
- public static int highGain;
- public static int heatDecay;
- public static int blockHeat;
- public static int punishHeat;
- public static boolean clearChat;
- public static String chatClearCommand;
- public static String spamPunishCommand;
- public static boolean logSpam;
- public static boolean antiSwearEnabled;
- public static int lowScore;
- public static int mediumLowScore;
- public static int mediumScore;
- public static int mediumHighScore;
- public static int highScore;
- public static int scoreDecay;
- public static int punishScore;
- public static boolean strictInstaPunish;
- public static String swearPunishCommand;
- public static String strictPunishCommand;
- public static boolean logSwear;
- public static List swearWhitelist;
- public static List swearBlacklist;
- public static List slurs;
- public static Map leetPatterns;
- public static FileConfiguration getConfig(String fileName) {
- File configFile = new File(Sentinel.getInstance().getDataFolder(), fileName);
-
- if (!configFile.exists()) {
- Sentinel.getInstance().saveResource(fileName, false);
- }
-
- return YamlConfiguration.loadConfiguration(configFile);
- }
- public static void loadConfiguration() {
-
- Sentinel.prefix = mainConfig.getString("config.plugin.prefix");
- Sentinel.key = mainConfig.getString("config.plugin.key");
- lang = mainConfig.getString("config.plugin.lang");
- webhook = mainConfig.getString("config.plugin.webhook");
- trustedPlayers = mainConfig.getStringList("config.plugin.trusted");
- blockSpecific = mainConfig.getBoolean("config.plugin.block-specific");
- preventNBT = mainConfig.getBoolean("config.plugin.prevent-nbt");
- preventCmdBlockPlace = mainConfig.getBoolean("config.plugin.prevent-cmdblock-place");
- preventCmdBlockUse = mainConfig.getBoolean("config.plugin.prevent-cmdblock-use");
- preventCmdBlockChange = mainConfig.getBoolean("config.plugin.prevent-cmdblock-change");
- preventCmdCartPlace = mainConfig.getBoolean("config.plugin.prevent-cmdcart-place");
- preventCmdCartUse = mainConfig.getBoolean("config.plugin.prevent-cmdcart-use");
- cmdBlockOpCheck = mainConfig.getBoolean("config.plugin.cmdblock-op-check");
- dangerous = mainConfig.getStringList("config.plugin.dangerous");
- logDangerous = mainConfig.getBoolean("config.plugin.log-dangerous");
- logCmdBlocks = mainConfig.getBoolean("config.plugin.log-cmdblocks");
- logNBT = mainConfig.getBoolean("config.plugin.log-nbt");
- logSpecific = mainConfig.getBoolean("config.plugin.log-specific");
- logged = mainConfig.getStringList("config.plugin.logged");
- deop = mainConfig.getBoolean("config.plugin.deop");
- nbtPunish = mainConfig.getBoolean("config.plugin.nbt-punish");
- cmdBlockPunish = mainConfig.getBoolean("config.plugin.cmdblock-punish");
- commandPunish = mainConfig.getBoolean("config.plugin.command-punish");
- specificPunish = mainConfig.getBoolean("config.plugin.specific-punish");
- punishCommands = mainConfig.getStringList("config.plugin.punish-commands");
- reopCommand = mainConfig.getBoolean("config.plugin.reop-command");
-
- // NBT
- allowName = nbtConfig.getBoolean("nbt.allow-name");
- allowLore = nbtConfig.getBoolean("nbt.allow-lore");
- allowAttributes = nbtConfig.getBoolean("nbt.allow-attributes");
- globalMaxEnchant = nbtConfig.getInt("nbt.global-max-enchant");
-
- // ALL
- maxMending = nbtConfig.getInt("nbt.max-mending");
- maxUnbreaking = nbtConfig.getInt("nbt.max-unbreaking");
- maxVanishing = nbtConfig.getInt("nbt.max-vanishing");
-
- // ARMOR
- maxAquaAffinity = nbtConfig.getInt("nbt.max-aqua-affinity");
- maxBlastProtection = nbtConfig.getInt("nbt.max-blast-protection");
- maxCurseOfBinding = nbtConfig.getInt("nbt.max-curse-of-binding");
- maxDepthStrider = nbtConfig.getInt("nbt.max-depth-strider");
- maxFeatherFalling = nbtConfig.getInt("nbt.max-feather-falling");
- maxFireProtection = nbtConfig.getInt("nbt.max-fire-protection");
- maxFrostWalker = nbtConfig.getInt("nbt.max-frost-walker");
- maxProjectileProtection = nbtConfig.getInt("nbt.max-projectile-protection");
- maxProtection = nbtConfig.getInt("nbt.max-protection");
- maxRespiration = nbtConfig.getInt("nbt.max-respiration");
- maxSoulSpeed = nbtConfig.getInt("nbt.max-soul-speed");
- maxThorns = nbtConfig.getInt("nbt.max-thorns");
- maxSwiftSneak = nbtConfig.getInt("nbt.max-swift-sneak");
-
- // MELEE WEAPONS
- maxBaneOfArthropods = nbtConfig.getInt("nbt.max-bane-of-arthropods");
- maxEfficiency = nbtConfig.getInt("nbt.max-efficiency");
- maxFireAspect = nbtConfig.getInt("nbt.max-fire-aspect");
- maxLooting = nbtConfig.getInt("nbt.max-looting");
- maxImpaling = nbtConfig.getInt("nbt.max-impaling");
- maxKnockback = nbtConfig.getInt("nbt.max-knockback");
- maxSharpness = nbtConfig.getInt("nbt.max-sharpness");
- maxSmite = nbtConfig.getInt("nbt.max-smite");
- maxSweepingEdge = nbtConfig.getInt("nbt.max-sweeping-edge");
-
- // RANGED WEAPONS
- maxChanneling = nbtConfig.getInt("nbt.max-channeling");
- maxFlame = nbtConfig.getInt("nbt.max-flame");
- maxInfinity = nbtConfig.getInt("nbt.max-infinity");
- maxLoyalty = nbtConfig.getInt("nbt.max-loyalty");
- maxRiptide = nbtConfig.getInt("nbt.max-riptide");
- maxMultishot = nbtConfig.getInt("nbt.max-multishot");
- maxPiercing = nbtConfig.getInt("nbt.max-piercing");
- maxPower = nbtConfig.getInt("nbt.max-power");
- maxPunch = nbtConfig.getInt("nbt.max-punch");
- maxQuickCharge = nbtConfig.getInt("nbt.max-quick-charge");
-
- // TOOLS
- maxEfficiency = nbtConfig.getInt("nbt.max-efficiency");
- maxFortune = nbtConfig.getInt("nbt.max-fortune");
- maxLuckOfTheSea = nbtConfig.getInt("nbt.max-luck-of-the-sea");
- maxLure = nbtConfig.getInt("nbt.max-lure");
- maxSilkTouch = nbtConfig.getInt("nbt.max-silk-touch");
-
- // Chat Filter Setup & AntiSpam
- antiUnicode = mainConfig.getBoolean("config.chat.anti-unicode");
- antiSpamEnabled = mainConfig.getBoolean("config.chat.anti-spam.enabled");
- defaultGain = mainConfig.getInt("config.chat.anti-spam.default-gain");
- lowGain = mainConfig.getInt("config.chat.anti-spam.low-gain");
- mediumGain = mainConfig.getInt("config.chat.anti-spam.medium-gain");
- highGain = mainConfig.getInt("config.chat.anti-spam.high-gain");
- heatDecay = mainConfig.getInt("config.chat.anti-spam.heat-decay");
- blockHeat = mainConfig.getInt("config.chat.anti-spam.block-heat");
- punishHeat = mainConfig.getInt("config.chat.anti-spam.punish-heat");
- clearChat = mainConfig.getBoolean("config.chat.anti-spam.clear-chat");
- chatClearCommand = mainConfig.getString("config.chat.anti-spam.chat-clear-command");
- spamPunishCommand = mainConfig.getString("config.chat.anti-spam.punish-command");
- logSpam = mainConfig.getBoolean("config.chat.anti-spam.log-spam");
- antiSwearEnabled = mainConfig.getBoolean("config.chat.anti-swear.enabled");
- lowScore = mainConfig.getInt("config.chat.anti-swear.low-score");
- mediumLowScore = mainConfig.getInt("config.chat.anti-swear.medium-low-score");
- mediumScore = mainConfig.getInt("config.chat.anti-swear.medium-score");
- mediumHighScore = mainConfig.getInt("config.chat.anti-swear.medium-high-score");
- highScore = mainConfig.getInt("config.chat.anti-swear.high-score");
- scoreDecay = mainConfig.getInt("config.chat.anti-swear.score-decay");
- punishScore = mainConfig.getInt("config.chat.anti-swear.punish-score");
- strictInstaPunish = mainConfig.getBoolean("config.chat.anti-swear.strict-insta-punish");
- swearPunishCommand = mainConfig.getString("config.chat.anti-swear.punish-command");
- strictPunishCommand = mainConfig.getString("config.chat.anti-swear.strict-command");
- logSwear = mainConfig.getBoolean("config.chat.anti-swear.log-swear");
- swearWhitelist = falsePositives.getStringList("false-positives");
- swearBlacklist = swearWords.getStringList("blacklisted");
- slurs = strictWords.getStringList("strict");
- leetPatterns = loadLeetPatterns();
- logSwear = mainConfig.getBoolean("config.chat.anti-swear.log-swear");
-
- }
- private static Map loadLeetPatterns() {
- Map dictionary = new HashMap<>();
- ConfigurationSection section = mainConfig.getConfigurationSection("config.chat.anti-swear.leet-patterns");
-
- if (section != null) {
- for (String key : section.getKeys(false)) {
- dictionary.put(key, section.getString(key));
- }
- }
-
- return dictionary;
- }
-
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java b/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java
index 88a332f..22b4177 100644
--- a/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java
+++ b/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java
@@ -1,13 +1,13 @@
package io.github.thetrouper.sentinel.data;
public class Emojis {
- public static String space = "<:space:1125871914334818446>";
- public static String rightSort = "<:rightSort:1125785837255270520>";
- public static String arrowRight = "<:arrowRight:1125785471520354304>";
- public static String rightDoubleArrow = "<:rightDoubleArrow:1125785800353783868>";
+ public static String space = "<:space:1210008300515762238>";
+ public static String rightSort = "<:rightSort:1210008337144479754>";
+ public static String rightArrow = "<:rightArrow:1210008295738179594>";
+ public static String rightDoubleArrow = "<:rightDoubleArrow:1210008296723976224>";
public static String activity = "<:activity:1125785527468167178>";
- public static String alarm = "<:alarm:1125790301873770606>";
- public static String target = "<:target:1125788461371232307>";
+ public static String alarm = "<:alarm:1210008289635475547>";
+ public static String target = "<:target:1210008303992701068>";
public static String bot = "<:bot:1125791121851826206>";
public static String cancel = "<:cancel:1125785769471127694>";
public static String creation = "<:creation:1125790610729730109>";
@@ -15,19 +15,19 @@ public class Emojis {
public static String kick = "<:kick:1125785612595761212>";
public static String members = "<:members:1125791101199077426>";
public static String mute = "<:mute:1125789032937435247>";
- public static String noDM = "<:noDM:1125790359423824022>";
+ public static String noDM = "<:noDM:1210008293729370204>";
public static String owner = "<:owner:1125791175559876669>";
public static String potentialDanger = "<:potentialDanger:1125788513971998741>";
public static String roles = "<:roles:1125790513933594645>";
public static String separator = "<:separator:1125790817626357861>";
public static String splash = "<:splash:1125791213933563905>";
- public static String success = "<:success:1125785728161419356>";
+ public static String success = "<:success:1210008354039275570>";
public static String suspicious = "<:suspicious:1125790709371371682>";
- public static String trustedAdmin = "<:trustedAdmin:1125785574591180822>";
+ public static String trustedAdmin = "<:trustedAdmin:1210008362230743080>";
public static String upvoter = "<:upvoter:1125790659735977994>";
public static String vanity = "<:vanity:1125791060594004039>";
public static String webhook = "<:webhook:1125790545638330388>";
- public static String failure = "<:failure:1125241087909429369>";
- public static String nuke = "<:nuke:1125244368807280702>";
- public static String member = "<:member:1125244044407218176>";
+ public static String failure = "<:failure:1210008290625462432>";
+ public static String nuke = "<:nuke:1210008294756712478>";
+ public static String member = "<:member:1210008291174785105>";
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FAT.java b/src/main/java/io/github/thetrouper/sentinel/data/FAT.java
deleted file mode 100644
index a10c09f..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/data/FAT.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.thetrouper.sentinel.data;
-
-import java.awt.*;
-
-public enum FAT {
- BLOCK_SWEAR("Sentinel Profanity Filter",null,"swear-block-warn", "swear-block-notification", null,null),
- BLOCK_SPAM("Sentinel Anti-Spam", null, "spam-block-warn", "spam-notification",null,null),
- SWEAR("Sentinel Anti-Swear Log","Anti-Swear", "profanity-mute-warn", "profanity-mute-notification", Config.swearPunishCommand, Color.orange),
- SLUR("Sentinel Anti-Slur Log", "Anti-Slur", "slur-mute-warn", "slur-mute-notification", Config.strictPunishCommand, Color.red),
- SPAM("Sentinel Anti-Spam Log", "Anti-Spam", "spam-mute-warn", "spam-mute-notification", Config.spamPunishCommand, Color.pink);
-
- private final String title;
- private final String name;
- private final String warnTranslationKey;
- private final String notifTranslationKey;
- private final String executedCommand;
- private final Color embedColor;
-
- FAT(String title, String name, String warnTranslationKey, String notifTranslationKey, String executedCommand, Color embedColor) {
- this.title = title;
- this.name = name;
- this.warnTranslationKey = warnTranslationKey;
- this.notifTranslationKey = notifTranslationKey;
- this.executedCommand = executedCommand;
- this.embedColor = embedColor;
- }
- public String getTitle() {
- return title;
- }
- public String getName() {
- return name;
- }
- public String getWarnTranslationKey() {
- return warnTranslationKey;
- }
-
- public String getNotifTranslationKey() {
- return notifTranslationKey;
- }
-
- public String getExecutedCommand() {
- return executedCommand;
- }
- public Color getColor() {
- return embedColor;
- }
-}
-
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java b/src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java
deleted file mode 100644
index 3b13352..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package io.github.thetrouper.sentinel.data;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.discord.DiscordWebhook;
-import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
-import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
-import io.github.thetrouper.sentinel.server.util.GPTUtils;
-import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
-import net.md_5.bungee.api.chat.ClickEvent;
-import net.md_5.bungee.api.chat.HoverEvent;
-import net.md_5.bungee.api.chat.TextComponent;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.AsyncPlayerChatEvent;
-
-import java.awt.*;
-import java.io.IOException;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-
-import static io.github.thetrouper.sentinel.server.functions.AntiSpam.heatMap;
-import static io.github.thetrouper.sentinel.server.functions.AntiSpam.lastMessageMap;
-import static io.github.thetrouper.sentinel.server.functions.ProfanityFilter.*;
-
-public class FilterAction {
-
- public static void filterAction(Player offender, AsyncPlayerChatEvent e, String highlighted, String severity, Double similarity, FAT type) {
- String report = ReportFalsePositives.generateReport(e);
-
- TextComponent warn = new TextComponent();
- warn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("action-automatic-reportable"))));
- warn.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));
-
- DecimalFormat fs = new DecimalFormat("##.#");
- fs.setRoundingMode(RoundingMode.DOWN);
-
- TextComponent notif = new TextComponent();
- notif.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText((type != FAT.SPAM && type != FAT.BLOCK_SPAM ? Sentinel.dict.get("severity-notification-hover").formatted(e.getMessage(), highlighted, severity) : Sentinel.dict.get("spam-notification-hover").formatted(e.getMessage(),lastMessageMap.get(offender),fs.format(similarity))))));
- notif.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));
-
- warn.setText(Text.prefix(Sentinel.dict.get(type.getWarnTranslationKey())));
- offender.spigot().sendMessage(warn);
-
- String notiftext = Sentinel.dict.get(type.getNotifTranslationKey());
-
- notif.setText(Text.prefix((type != FAT.SPAM && type != FAT.BLOCK_SPAM ? notiftext.formatted(offender.getName(), scoreMap.get(offender), Config.punishScore) : notiftext.formatted(offender.getName(),heatMap.get(offender),Config.punishHeat))));
-
- ServerUtils.forEachStaff(staffmember -> {
- staffmember.spigot().sendMessage(notif);
- });
-
- if (type.getExecutedCommand() != null) {
- ServerUtils.sendCommand(type.getExecutedCommand().replace("%player%", offender.getName()));
- }
-
- if (type == FAT.SWEAR && Config.logSwear) {
- sendDiscordLog(offender,e,type);
- sendConsoleLog(offender,e,type);
- }
-
- if (type == FAT.SLUR && Config.logSwear) {
- sendDiscordLog(offender,e,type);
- sendConsoleLog(offender,e,type);
- }
- if (type == FAT.SPAM && Config.logSpam) {
- sendDiscordLog(offender,e,type);
- sendConsoleLog(offender,e,type);
- }
- }
- public static void sendConsoleLog(Player offender, AsyncPlayerChatEvent e, FAT type) {
- String log = "]=-" + type.getTitle() + "-=[\n" +
- "Player: " + offender.getName() +
- (type != FAT.BLOCK_SPAM && type != FAT.SPAM ? "> Score: `" + scoreMap.get(offender) + "/" + Config.punishScore : "> Heat: `" + heatMap.get(offender) + "/" + Config.punishHeat) + "\n" +
- "> UUID: " + offender.getUniqueId() + "\n" +
- (type != FAT.BLOCK_SPAM && type != FAT.SPAM ? "Message: " + e.getMessage() : "Previous: " + lastMessageMap.get(offender)) + "\n" +
- (type != FAT.BLOCK_SPAM && type != FAT.SPAM ? "Reduced: " + fullSimplify(e.getMessage()) : "Current: " + e.getMessage()) + "\n" +
- (type.getExecutedCommand() != null ? "Executed: " + type.getExecutedCommand() : "Executed: Nothing, its a standard flag. You shouldn't be seeing this, please report it.");
- Sentinel.log.info(log);
- }
-
- private static void sendDiscordLog(Player offender, AsyncPlayerChatEvent e, FAT type) {
- String supertitle = type.getTitle();
- String title = offender.getName() + " has triggered the " + type.getName() + "!";
- String executed = type.getExecutedCommand() != null ? type.getExecutedCommand() : "Nothing, its a standard flag. You shouldn't be seeing this, please report it.";
-
- DiscordWebhook webhook = new DiscordWebhook(Config.webhook);
- webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png");
- webhook.setUsername("Sentinel Anti-Nuke | Logs");
-
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor(supertitle, "", "")
- .setTitle(title)
- .setDescription(
- Emojis.rightSort + "Player: " + offender.getName() + " " + Emojis.target + "\\n" +
- Emojis.space + Emojis.arrowRight + (type != FAT.BLOCK_SPAM ? "Score: `" + scoreMap.get(offender) + "/" + Config.punishScore : "Heat: `" + heatMap.get(offender) + "/" + Config.punishHeat) + "`\\n" +
- Emojis.space + Emojis.arrowRight + "UUID: `" + offender.getUniqueId() + "`\\n" +
- Emojis.rightSort + "Executed: " + executed + " " + Emojis.mute + "\\n"
- )
- .addField((type != FAT.BLOCK_SPAM && type != FAT.SPAM ? "Message: " : "Previous: "), (type != FAT.BLOCK_SPAM && type != FAT.SPAM ? e.getMessage() : lastMessageMap.get(offender)) + Emojis.alarm, false)
- .addField((type != FAT.BLOCK_SPAM && type != FAT.SPAM ? "Reduced: " : "Current: "), (type != FAT.BLOCK_SPAM && type != FAT.SPAM ? highlightProfanity(e.getMessage(), "||", "||") : e.getMessage()) + " " + Emojis.noDM, false)
- .setColor(type.getColor())
- .setThumbnail("https://crafatar.com/avatars/" + offender.getUniqueId() + "?size=64&&overlay");
-
- webhook.addEmbed(embed);
-
- try {
- ServerUtils.sendDebugMessage("Executing webhook...");
- webhook.execute();
- } catch (IOException ex) {
- ServerUtils.sendDebugMessage("Filter Actions: Epic webhook failure!!!");
- Sentinel.log.info(ex.toString());
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FilterActionType.java b/src/main/java/io/github/thetrouper/sentinel/data/FilterActionType.java
new file mode 100644
index 0000000..ebc2eab
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/FilterActionType.java
@@ -0,0 +1,15 @@
+package io.github.thetrouper.sentinel.data;
+
+import io.github.thetrouper.sentinel.Sentinel;
+
+public record FilterActionType(String logSuper, String logName, String chatWarning, String chatWarningHover, String chatNotification, String chatNotificationHover, String punishmentCommand, int embedColor, boolean isLogged) {
+
+ public static final FilterActionType UNICODE_BLOCK = new FilterActionType("Sentinel Anti-Unicode Log", "Anti-Unicode", Sentinel.lang.unicodeFilter.unicodeWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.unicodeFilter.unicodeNotification, Sentinel.lang.unicodeFilter.unicodeNotificationHover, null, 0xAAAAFF, Sentinel.mainConfig.chat.logUnicode);
+ public static final FilterActionType URL_BLOCK = new FilterActionType("Sentinel Anti-URL Log", "Anti-URL", Sentinel.lang.urlFilter.urlWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.urlFilter.urlNotification, Sentinel.lang.urlFilter.urlNotificationHover, null, 0xAAAAFF, Sentinel.mainConfig.chat.logURL);
+ public static final FilterActionType SPAM_BLOCK = new FilterActionType("Sentinel Anti-Spam Log", "Anti-Spam", Sentinel.lang.spamFilter.spamWarn, Sentinel.lang.automatedActions.actionAutomatic, Sentinel.lang.spamFilter.spamNotification, Sentinel.lang.spamFilter.spamNotificationHover, null, 0xFFFF00, Sentinel.mainConfig.chat.antiSpam.logAllSpam);
+ public static final FilterActionType SPAM_PUNISH = new FilterActionType("Sentinel Anti-Spam Log", "Anti-Spam", Sentinel.lang.spamFilter.spamMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.spamFilter.spamMuteNotification, Sentinel.lang.spamFilter.spamNotificationHover, Sentinel.mainConfig.chat.antiSpam.spamPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSpam.logSpamPunishments);
+ public static final FilterActionType SWEAR_BLOCK = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Swear", Sentinel.lang.profanityFilter.profanityWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.profanityFilter.profanityNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, null, 0xFFFF00, Sentinel.mainConfig.chat.antiSwear.logAllSwears);
+ public static final FilterActionType SWEAR_PUNISH = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Swear", Sentinel.lang.profanityFilter.profanityMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.profanityFilter.profanityMuteNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, Sentinel.mainConfig.chat.antiSwear.swearPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSwear.logSwearPunishments);
+ public static final FilterActionType SLUR_PUNISH = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Slur", Sentinel.lang.slurFilter.slurMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.slurFilter.slurMuteNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, Sentinel.mainConfig.chat.antiSwear.strictPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSwear.logSwearPunishments);
+ public static final FilterActionType SAFE = new FilterActionType("ERROR", null, null, null, null, null, null, 0x00AA00,false);
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FilterSeverity.java b/src/main/java/io/github/thetrouper/sentinel/data/FilterSeverity.java
new file mode 100644
index 0000000..2eb93b9
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/FilterSeverity.java
@@ -0,0 +1,23 @@
+package io.github.thetrouper.sentinel.data;
+
+import io.github.thetrouper.sentinel.Sentinel;
+
+public enum FilterSeverity {
+ LOW(Sentinel.mainConfig.chat.antiSwear.lowScore),
+ MEDIUM_LOW(Sentinel.mainConfig.chat.antiSwear.mediumLowScore),
+ MEDIUM(Sentinel.mainConfig.chat.antiSwear.mediumScore),
+ MEDIUM_HIGH(Sentinel.mainConfig.chat.antiSwear.mediumHighScore),
+ HIGH(Sentinel.mainConfig.chat.antiSwear.highScore),
+ SLUR(Sentinel.mainConfig.chat.antiSwear.highScore),
+ SAFE(0);
+
+ private final int score;
+
+ FilterSeverity(int score) {
+ this.score = score;
+ }
+
+ public int getScore() {
+ return score;
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java b/src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java
deleted file mode 100644
index e87d854..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.github.thetrouper.sentinel.data;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.util.JsonSerializable;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-public class LanguageFile implements JsonSerializable {
- public static final File PATH = new File(Sentinel.getInstance().getDataFolder(), "/lang/" + Config.lang);
- private final Map dictionary = new HashMap<>();
- public LanguageFile() {}
-
- @Override
- public File getFile() {
- return PATH;
- }
- public String get(String key) {
- return dictionary.getOrDefault(key,key);
- }
- public Map getDictionary() {
- return dictionary;
- }
- public String format(String input) {
- return input;
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/NewActionType.java b/src/main/java/io/github/thetrouper/sentinel/data/NewActionType.java
new file mode 100644
index 0000000..62844ab
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/NewActionType.java
@@ -0,0 +1,15 @@
+package io.github.thetrouper.sentinel.data;
+
+public record NewActionType(String superTitle, String title, int embedColor, String chatNotification) {
+ public static final NewActionType CMD_BLOCK_EXECUTE = new NewActionType("Command Block Whitelist Log", "An unauthorized command block has been detected",0xFF0000,"The Command Block Whitelist has been triggered!");
+ public static final NewActionType CMD_BLOCK_PLACE = new NewActionType("Anti-Nuke Log", "A player attempted to place a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_BLOCK_USE = new NewActionType("Anti-Nuke Log", "A player attempted to use a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_BLOCK_CHANGE = new NewActionType("Anti-Nuke Log", "A player attempted to change a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_MINECART_USE = new NewActionType("Anti-Nuke Log", "A player attempted to use a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_MINECART_PLACE = new NewActionType("Anti-Nuke Log", "A player attempted to place a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_MINECART_BREAK = new NewActionType("Anti-Nuke Log", "A player attempted to break a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_EXECUTE = new NewActionType("Anti-Nuke Log", "A player attempted to run a dangerous command",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
+ public static final NewActionType CMD_SPECIFIC = new NewActionType("Anti-Specific Log", "A player attempted to run a plugin specific command",0xFF0000,"§e%s§7 has triggered the Anti-Specific.");
+ public static final NewActionType CMD_LOGGED = new NewActionType("Command Log", "A player has ran a logged command",0xFF0000,"§e%s§7 has ran a logged command.");
+ public static final NewActionType NBT_PULL = new NewActionType("Anti-NBT Log", "A player attempted to pull out an NBT item",0xFF0000,"§e%s§7 has triggered the Anti-NBT!");
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Report.java b/src/main/java/io/github/thetrouper/sentinel/data/Report.java
new file mode 100644
index 0000000..f983fa8
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/Report.java
@@ -0,0 +1,8 @@
+package io.github.thetrouper.sentinel.data;
+
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+
+import java.util.LinkedHashMap;
+
+public record Report(long id, AsyncPlayerChatEvent event, LinkedHashMap stepsTaken) {
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/CMDBlockType.java b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/CMDBlockType.java
new file mode 100644
index 0000000..872017b
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/CMDBlockType.java
@@ -0,0 +1,7 @@
+package io.github.thetrouper.sentinel.data.cmdblocks;
+
+public enum CMDBlockType {
+ CHAIN,
+ REPEAT,
+ IMPULSE,
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/Location.java b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/Location.java
new file mode 100644
index 0000000..9eb7234
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/Location.java
@@ -0,0 +1,4 @@
+package io.github.thetrouper.sentinel.data.cmdblocks;
+
+public record Location(String world, double x, double y,double z) {
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistStorage.java b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistStorage.java
new file mode 100644
index 0000000..482aa71
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistStorage.java
@@ -0,0 +1,20 @@
+package io.github.thetrouper.sentinel.data.cmdblocks;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class WhitelistStorage implements JsonSerializable {
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/storage/whitelist.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+
+ public ConcurrentLinkedQueue whitelistedCMDBlocks = new ConcurrentLinkedQueue<>();
+
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistedBlock.java b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistedBlock.java
new file mode 100644
index 0000000..0082d7c
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/cmdblocks/WhitelistedBlock.java
@@ -0,0 +1,15 @@
+package io.github.thetrouper.sentinel.data.cmdblocks;
+
+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/io/github/thetrouper/sentinel/data/config/AdvancedConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/AdvancedConfig.java
new file mode 100644
index 0000000..0cfc7e2
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/AdvancedConfig.java
@@ -0,0 +1,66 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AdvancedConfig implements JsonSerializable {
+
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/advanced-config.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+ public List fakePlugins = Arrays.asList(
+ "This server wishes to keep their plugins confidential. Anyways, Enjoy your meteor client! If the owner is incompetent, then .server plugins MassScan should still work ;)",
+ "NoCheatPlus",
+ "Negativity",
+ "Warden",
+ "Horizon",
+ "Illegalstack",
+ "CoreProtect",
+ "ExploitsX",
+ "Vulcan (Outdated version frfr)",
+ "ABC",
+ "Spartan",
+ "Kauri",
+ "AnticheatReloaded",
+ "WitherAC",
+ "GodsEye",
+ "Matrix",
+ "Wraith",
+ "AntiXrayHeuristics",
+ "GrimAC"
+ );
+
+ public String[] versionAliases = {"version", "ver", "about", "bukkit:version", "bukkit:ver", "bukkit:about", "?", "bukkit:?","pl","bukkit:pl","plugins","bukkit:plugins","bukkit:help"};
+
+ public Map leetPatterns = new HashMap<>() {{
+ put("0", "o");
+ put("1", "i");
+ put("3", "e");
+ put("4", "a");
+ put("5", "s");
+ put("6", "g");
+ put("7", "l");
+ put("$", "s");
+ put("!", "i");
+ put("|", "i");
+ put("+", "t");
+ put("#", "h");
+ put("@", "a");
+ put("<", "c");
+ put("V", "u");
+ put("v", "u");
+ }};
+ public String allowedCharRegex = "[A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_]";
+ public String falsePosRegex = "";
+ public String swearRegex = "";
+ public String strictRegex = "";
+ public String urlRegex = "\\b(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:com|org|net|int|edu|gov|mil|arpa|biz|info|mobi|app|name|aero|jobs|museum|travel|a[c-gil-oq-uwxz]|b[abd-jmnoq-tvwyz]|c[acdf-ik-orsu-z]|d[dejkmoz]|e[ceghr-u]|f[ijkmor]|g[abd-ilmnp-uwy]|h[kmnrtu]|i[delmnoq-t]|j[emop]|k[eghimnprwyz]|l[abcikr-vy]|m[acdeghk-z]|n[acefgilopruz]|om|p[ae-hk-nrstwy]|qa|r[eosuw]|s[a-eg-or-vxyz]|t[cdfghj-prtvwz]|u[agksyz]|v[aceginu]|w[fs]|y[etu]|z[amrw])))(?::\\d{2,5})?(?:\\/\\S*)?\\b";
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/FPConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/FPConfig.java
new file mode 100644
index 0000000..30d32ac
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/FPConfig.java
@@ -0,0 +1,78 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class FPConfig implements JsonSerializable {
+
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/false-positives.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+
+ public List swearWhitelist = new ArrayList<>(Arrays.asList(
+ "but then",
+ "was scamming",
+ "an alt",
+ "can also",
+ "analysis",
+ "analytics",
+ "arsenal",
+ "assassin",
+ "as saying",
+ "assert",
+ "assign",
+ "assimil",
+ "assist",
+ "associat",
+ "assum",
+ "assur",
+ "basement",
+ "bass",
+ "cass",
+ "butter",
+ "canvass",
+ "cocktail",
+ "cumber",
+ "document",
+ "evaluate",
+ "exclusive",
+ "expensive",
+ "explain",
+ "expression",
+ "grape",
+ "grass",
+ "harass",
+ "hotwater",
+ "identit",
+ "kassa",
+ "kassi",
+ "lass",
+ "leafage",
+ "libshitz",
+ "magnacumlaude",
+ "mass",
+ "mocha",
+ "pass",
+ "phoebe",
+ "phoenix",
+ "push it",
+ "sassy",
+ "saturday",
+ "scrap",
+ "serfage",
+ "sexist",
+ "shoe",
+ "stitch",
+ "therapist",
+ "but its",
+ "whoever",
+ " again"
+ ));
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java b/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java
new file mode 100644
index 0000000..b645940
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java
@@ -0,0 +1,103 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+import io.github.thetrouper.sentinel.Sentinel;
+
+import java.io.File;
+
+public class LanguageFile implements JsonSerializable {
+ public static final File PATH = new File(Sentinel.getInstance().getDataFolder(), "/lang/" + Sentinel.mainConfig.plugin.lang);
+ public LanguageFile() {}
+
+ @Override
+ public File getFile() {
+ return PATH;
+ }
+
+ public String brokenLang = "Sentinel language is working!";
+
+ public Permissions permissions = new Permissions();
+ public class Permissions {
+ public String noPermission = "§cInsufficient Permissions!";
+ public String elevatingPerms = "Elevating your permissions...";
+ public String logElevatingPerms = "Elevating the permissions of %s";
+ public String alreadyOp = "You are already a server operator!";
+ public String logAlreadyOp = "The permissions of %s are already elevated! Retrying...";
+ public String noTrust = "You are not a trusted user!";
+ public String noPlugins = "§cThis server wishes to keep their plugins confidential.";
+ }
+
+ public Cooldown cooldown = new Cooldown();
+ public class Cooldown {
+ public String onCooldown = "This action is on cooldown!";
+ }
+
+ public Reports reports = new Reports();
+ public class Reports {
+ public String falsePositiveSuccess = "Successfully reported a false positive!";
+ public String reportingFalsePositive = "Sending report to staff...";
+ public String noReport = "§cThe report you requested either does not exist, or has expired!";
+ }
+
+ public PlayerInteraction playerInteraction = new PlayerInteraction();
+ public class PlayerInteraction {
+ public String noOnlinePlayer = "§cYou must provide an online player to send a message to!";
+ public String noMessageProvided = "§cYou must provide a message to send!";
+ public String noReply = "§cYou have nobody to reply to!";
+ public String messageSent = "§d§lMessage §8» §b[§fYou §e>§f %1$s§b] §7%2$s";
+ public String messageReceived = "§d§lMessage §8» §b[§f%1$s §e>§f You§b] §7%2$s";
+ }
+
+ public SocialSpy socialSpy = new SocialSpy();
+ public class SocialSpy {
+ public String enabled = "SocialSpy is now enabled.";
+ public String disabled = "SocialSpy is now disabled.";
+ public String spyMessage = "§d§lSpy §8» §b§n%1$s§7 has messaged §b§n%2$s§7.";
+ public String spyMessageHover = "§8]==-- §d§lSocialSpy §8--==[\n§bSender: §f%1$S\n§bReceiver: §f%2$S\n§bMessage: §f%3$S";
+ }
+
+ public AutomatedActions automatedActions = new AutomatedActions();
+ public class AutomatedActions {
+ public String actionAutomatic = "§7This action was preformed automatically\n§7by the §bSentinel Chat Filter§7 algorithm.";
+ public String actionAutomaticReportable = "§7This action was preformed automatically \n§7by the §bSentinel Chat Filter§7 algorithm!\n§8§o(Click to report false positive)";
+ }
+
+ public ProfanityFilter profanityFilter = new ProfanityFilter();
+ public class ProfanityFilter {
+ public String profanityNotification = "§b§n%1$s§7 has triggered the anti-swear! §8(§c%2$s§7/§4%3$s§8)";
+ public String profanityWarn = "§cPlease do not swear in chat! Attempting to bypass this filter will result in a mute! §7§o(Hover for more info)";
+ public String profanityMuteWarn = "You have been auto-muted for repeated violation of the profanity filter! §7§o(Hover for more info)";
+ public String profanityMuteNotification = "§b§n%1$s§7 has been auto-muted by the profanity filter! §8(§c%2$s§7/§4%3$s§8)";
+ public String profanityNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§bSeverity: §c%3$s\n§7§o(click to report false positive)";
+ }
+
+ public SlurFilter slurFilter = new SlurFilter();
+ public class SlurFilter {
+ public String slurMuteWarn = "§cYou have been insta-punished by the anti-slur! §7§o(Hover for more info)";
+ public String slurMuteNotification = "§b§n%1$s§7 has been insta-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)";
+ }
+
+ public SpamFilter spamFilter = new SpamFilter();
+ public class SpamFilter {
+ public String spamNotification = "§b§n%1$s§7 might be spamming! §8(§c%2$s§7/§4%3$s§8)";
+ public String spamNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bPrevious: §f%1$s\n§bCurrent: §f%2$s\n§bSimilarity §f%3$s";
+ public String spamWarn = "Do not spam in chat! Please wait before sending another message.";
+ public String spamMuteWarn = "§cYou have been auto-punished for violating the anti-spam repetitively!";
+ public String spamMuteNotification = "§b§n%1$s§7 has been auto-muted by the anti spam! §8(§c%2$s§7/§4%3$s§8)";
+ }
+
+ public URLFilter urlFilter = new URLFilter();
+ public class URLFilter {
+ public String urlWarn = "§cDo not send urls in chat!";
+ public String urlNotification = "§b§n%1$s§7 has triggered the anti-URL.";
+ public String urlNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bDetected: §f%1$s";
+ }
+
+ public UnicodeFilter unicodeFilter = new UnicodeFilter();
+ public class UnicodeFilter {
+ public String unicodeWarn = "§cDo not send non-standard unicode in chat!";
+ public String unicodeNotification = "§b§n%1$s§7 has triggered the anti-unicode.";
+ public String unicodeNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bMessage: §f%1$s";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java
new file mode 100644
index 0000000..ab33c91
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java
@@ -0,0 +1,126 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.List;
+
+public class MainConfig implements JsonSerializable {
+
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/main-config.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+ public Plugin plugin = new Plugin();
+ public Chat chat = new Chat();
+
+ public class Plugin {
+ public String license = "null";
+ public String prefix = "§d§lSentinel §8» §7";
+ public String webhook = "https://discord.com/api/webhooks/id/token";
+ public String lang = "en-us.json";
+ public List trustedPlayers = List.of(
+ "049460f7-21cb-42f5-8059-d42752bf406f"
+ );
+ public boolean blockSpecific = true;
+ public boolean preventNBT = true;
+ public boolean preventCmdBlockPlace = true;
+ public boolean preventCmdBlockUse = true;
+ public boolean preventCmdBlockChange = true;
+ public boolean cmdBlockWhitelist = false;
+ public boolean deleteUnauthorizedCmdBlocks = false;
+ public boolean logUnauthorizedCmdBlocks = false;
+ public boolean preventCmdCartPlace = true;
+ public boolean preventCmdCartUse = true;
+ public boolean cmdBlockOpCheck = true;
+ public List dangerous = List.of(
+ "op",
+ "deop",
+ "stop",
+ "restart",
+ "execute",
+ "sudo",
+ "esudo",
+ "fill",
+ "setblock",
+ "data",
+ "whitelist",
+ "lp",
+ "luckperms",
+ "perms",
+ "perm",
+ "permission",
+ "permissions",
+ "pm",
+ "pluginmanager",
+ "rl",
+ "reload",
+ "plugman"
+ );
+ public boolean logDangerous = true;
+ public boolean logCmdBlocks = true;
+ public boolean logNBT = true;
+ public boolean logSpecific = false;
+ public List logged = List.of(
+ "give",
+ "item"
+ );
+ public boolean deop = true;
+ public boolean nbtPunish = false;
+ public boolean cmdBlockPunish = false;
+ public boolean commandPunish = false;
+ public boolean specificPunish = false;
+ public List punishCommands = List.of(
+ "smite %player%",
+ "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 boolean reopCommand = false;
+ public boolean pluginHider = true;
+ }
+
+ public class Chat {
+ public AntiSwear antiSwear = new AntiSwear();
+ public AntiSpam antiSpam = new AntiSpam();
+ public boolean useAntiURL = true;
+ public boolean useSwearRegex = false;
+ public boolean useStrictRegex = false;
+ public boolean useAntiUnicode = true;
+ public boolean logURL = true;
+ public boolean logUnicode = true;
+
+
+ public class AntiSpam {
+ public boolean antiSpamEnabled = true;
+ public int defaultGain = 1;
+ public int lowGain = 2;
+ public int mediumGain = 4;
+ public int highGain = 6;
+ public int heatDecay = 1;
+ public int blockHeat = 10;
+ public int punishHeat = 25;
+ public boolean clearChat = true;
+ public String chatClearCommand = "cc";
+ public String spamPunishCommand = "mute %player% 1m Please refrain from spamming!";
+ public boolean logAllSpam = false;
+ public boolean logSpamPunishments = true;
+ }
+
+ public class AntiSwear {
+ public boolean antiSwearEnabled = true;
+ public int lowScore = 0;
+ public int mediumLowScore = 1;
+ public int mediumScore = 3;
+ public int mediumHighScore = 5;
+ public int highScore = 7;
+ public int scoreDecay = 3;
+ public int punishScore = 20;
+ public String swearPunishCommand = "mute %player% 15m Do not attempt to bypass the Profanity Filter";
+ public String strictPunishCommand = "mute %player% 1h Discriminatory speech is not tolerated on this server!";
+ public boolean logAllSwears = false;
+ public boolean logSwearPunishments = true;
+ }
+
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/NBTConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/NBTConfig.java
new file mode 100644
index 0000000..72e1f04
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/NBTConfig.java
@@ -0,0 +1,59 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+
+public class NBTConfig implements JsonSerializable {
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/nbt-config.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+
+ public boolean allowName = true;
+ public boolean allowLore = true;
+ public boolean allowAttributes = false;
+ public boolean allowPotions = false;
+ public int globalMaxEnchant = 5;
+ public int maxMending = 1;
+ public int maxUnbreaking = 3;
+ public int maxVanishing = 1;
+ public int maxAquaAffinity = 1;
+ public int maxBlastProtection = 4;
+ public int maxCurseOfBinding = 1;
+ public int maxDepthStrider = 3;
+ public int maxFeatherFalling = 4;
+ public int maxFireProtection = 4;
+ public int maxFrostWalker = 2;
+ public int maxProjectileProtection = 4;
+ public int maxProtection = 4;
+ public int maxRespiration = 3;
+ public int maxSoulSpeed = 3;
+ public int maxThorns = 3;
+ public int maxSwiftSneak = 3;
+ public int maxBaneOfArthropods = 5;
+ public int maxEfficiency = 5;
+ public int maxFireAspect = 2;
+ public int maxLooting = 3;
+ public int maxImpaling = 5;
+ public int maxKnockback = 2;
+ public int maxSharpness = 5;
+ public int maxSmite = 5;
+ public int maxSweepingEdge = 3;
+ public int maxChanneling = 1;
+ public int maxFlame = 1;
+ public int maxInfinity = 1;
+ public int maxLoyalty = 3;
+ public int maxRiptide = 3;
+ public int maxMultishot = 1;
+ public int maxPiercing = 4;
+ public int maxPower = 5;
+ public int maxPunch = 2;
+ public int maxQuickCharge = 3;
+ public int maxFortune = 3;
+ public int maxLuckOfTheSea = 3;
+ public int maxLure = 3;
+ public int maxSilkTouch = 1;
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/StrictConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/StrictConfig.java
new file mode 100644
index 0000000..573e6a7
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/StrictConfig.java
@@ -0,0 +1,27 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class StrictConfig implements JsonSerializable {
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/strict.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+
+ public List strict = new ArrayList<>() {{
+ add("nigg");
+ add("niger");
+ add("nlgg");
+ add("nlger");
+ add("njgg");
+ add("tranny");
+ add("fag");
+ add("beaner");
+ }};
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java
new file mode 100644
index 0000000..f5dc636
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java
@@ -0,0 +1,96 @@
+package io.github.thetrouper.sentinel.data.config;
+
+import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
+
+import java.io.File;
+import java.util.List;
+
+public class SwearsConfig implements JsonSerializable {
+ @Override
+ public File getFile() {
+ File file = new File("plugins/Sentinel/swears.json");
+ file.getParentFile().mkdirs();
+ return file;
+ }
+
+ public List swears = List.of(
+ "anal",
+ "anus",
+ "arse",
+ "ass",
+ "ballsack",
+ "balls",
+ "bastard",
+ "bitch",
+ "btch",
+ "biatch",
+ "blowjob",
+ "bollock",
+ "bollok",
+ "boner",
+ "boob",
+ "bugger",
+ "butt",
+ "choad",
+ "clitoris",
+ "cock",
+ "coon",
+ "crap",
+ "cum",
+ "cunt",
+ "dick",
+ "dildo",
+ "douchebag",
+ "dyke",
+ "feck",
+ "fellate",
+ "fellatio",
+ "felching",
+ "fuck",
+ "fudgepacker",
+ "flange",
+ "gtfo",
+ "hoe",
+ "horny",
+ "incest",
+ "jerk",
+ "jizz",
+ "labia",
+ "masturb",
+ "muff",
+ "nazi",
+ "nipple",
+ "nips",
+ "nude",
+ "pedophile",
+ "penis",
+ "piss",
+ "poop",
+ "porn",
+ "prick",
+ "prostit",
+ "pube",
+ "pussie",
+ "pussy",
+ "queer",
+ "rape",
+ "rapist",
+ "retard",
+ "rimjob",
+ "scrotum",
+ "sex",
+ "shit",
+ "slut",
+ "spunk",
+ "stfu",
+ "suckmy",
+ "tits",
+ "tittie",
+ "titty",
+ "turd",
+ "twat",
+ "vagina",
+ "wank",
+ "whore"
+ );
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java b/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java
deleted file mode 100644
index 2cf3e7e..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java
+++ /dev/null
@@ -1,426 +0,0 @@
-package io.github.thetrouper.sentinel.discord;
-
-import javax.net.ssl.HttpsURLConnection;
-import java.awt.Color;
-import java.io.*;
-import java.lang.reflect.Array;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Class used to execute Discord Webhooks with low effort
- */
-public class DiscordWebhook {
-
- private final String url;
- private String content;
- private String username;
- private String avatarUrl;
- private boolean tts;
- private final List embeds = new ArrayList<>();
- private final List attachments = new ArrayList<>();
-
- /**
- * Constructs a new DiscordWebhook instance
- *
- * @param url The webhook URL obtained in Discord
- */
- public DiscordWebhook(String url) {
- this.url = url;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public void setAvatarUrl(String avatarUrl) {
- this.avatarUrl = avatarUrl;
- }
-
- public void setTts(boolean tts) {
- this.tts = tts;
- }
-
- public void addEmbed(EmbedObject embed) {
- this.embeds.add(embed);
- }
-
- public void addAttachment(String filename, String content) {
- attachments.add(new Attachment(filename, content));
- }
-
- public void execute() throws IOException {
- if (this.content == null && this.embeds.isEmpty() && this.attachments.isEmpty()) {
- throw new IllegalArgumentException("Set content, add at least one EmbedObject, or add an attachment");
- }
-
- JSONObject json = new JSONObject();
-
- json.put("content", this.content);
- json.put("username", this.username);
- json.put("avatar_url", this.avatarUrl);
- json.put("tts", this.tts);
-
- if (!this.embeds.isEmpty()) {
- List embedObjects = new ArrayList<>();
-
- for (EmbedObject embed : this.embeds) {
- JSONObject jsonEmbed = new JSONObject();
-
- jsonEmbed.put("title", embed.getTitle());
- jsonEmbed.put("description", embed.getDescription());
- jsonEmbed.put("url", embed.getUrl());
-
- if (embed.getColor() != null) {
- Color color = embed.getColor();
- int rgb = color.getRed();
- rgb = (rgb << 8) + color.getGreen();
- rgb = (rgb << 8) + color.getBlue();
-
- jsonEmbed.put("color", rgb);
- }
-
- EmbedObject.Footer footer = embed.getFooter();
- EmbedObject.Image image = embed.getImage();
- EmbedObject.Thumbnail thumbnail = embed.getThumbnail();
- EmbedObject.Author author = embed.getAuthor();
- List fields = embed.getFields();
-
- if (footer != null) {
- JSONObject jsonFooter = new JSONObject();
-
- jsonFooter.put("text", footer.getText());
- jsonFooter.put("icon_url", footer.getIconUrl());
- jsonEmbed.put("footer", jsonFooter);
- }
-
- if (image != null) {
- JSONObject jsonImage = new JSONObject();
-
- jsonImage.put("url", image.getUrl());
- jsonEmbed.put("image", jsonImage);
- }
-
- if (thumbnail != null) {
- JSONObject jsonThumbnail = new JSONObject();
-
- jsonThumbnail.put("url", thumbnail.getUrl());
- jsonEmbed.put("thumbnail", jsonThumbnail);
- }
-
- if (author != null) {
- JSONObject jsonAuthor = new JSONObject();
-
- jsonAuthor.put("name", author.getName());
- jsonAuthor.put("url", author.getUrl());
- jsonAuthor.put("icon_url", author.getIconUrl());
- jsonEmbed.put("author", jsonAuthor);
- }
-
- List jsonFields = new ArrayList<>();
- for (EmbedObject.Field field : fields) {
- JSONObject jsonField = new JSONObject();
-
- jsonField.put("name", field.getName());
- jsonField.put("value", field.getValue());
- jsonField.put("inline", field.isInline());
-
- jsonFields.add(jsonField);
- }
-
- jsonEmbed.put("fields", jsonFields.toArray());
- embedObjects.add(jsonEmbed);
- }
-
- json.put("embeds", embedObjects.toArray());
- }
-
- if (!this.attachments.isEmpty()) {
- List attachmentObjects = new ArrayList<>();
-
- for (Attachment attachment : this.attachments) {
- JSONObject attachmentObject = new JSONObject();
- attachmentObject.put("name", attachment.getFilename());
- attachmentObject.put("content", attachment.getContent());
- attachmentObjects.add(attachmentObject);
- }
-
- json.put("attachments", attachmentObjects.toArray());
- }
-
- URL url = new URL(this.url);
- HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
- connection.addRequestProperty("Content-Type", "application/json");
- connection.addRequestProperty("User-Agent", "Java-DiscordWebhook-BY-Gelox_");
- connection.setDoOutput(true);
- connection.setRequestMethod("POST");
-
- OutputStream stream = connection.getOutputStream();
- stream.write(json.toString().getBytes());
- stream.flush();
- stream.close();
-
- connection.getInputStream().close(); //I'm not sure why but it doesn't work without getting the InputStream
- connection.disconnect();
- }
-
- public static class EmbedObject {
- private String title;
- private String description;
- private String url;
- private Color color;
-
- private Footer footer;
- private Thumbnail thumbnail;
- private Image image;
- private Author author;
- private final List fields = new ArrayList<>();
-
- public String getTitle() {
- return title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public String getUrl() {
- return url;
- }
-
- public Color getColor() {
- return color;
- }
-
- public Footer getFooter() {
- return footer;
- }
-
- public Thumbnail getThumbnail() {
- return thumbnail;
- }
-
- public Image getImage() {
- return image;
- }
-
- public Author getAuthor() {
- return author;
- }
-
- public List getFields() {
- return fields;
- }
-
- public EmbedObject setTitle(String title) {
- this.title = title;
- return this;
- }
-
- public EmbedObject setDescription(String description) {
- this.description = description;
- return this;
- }
-
- public EmbedObject setUrl(String url) {
- this.url = url;
- return this;
- }
-
- public EmbedObject setColor(Color color) {
- this.color = color;
- return this;
- }
-
- public EmbedObject setFooter(String text, String icon) {
- this.footer = new Footer(text, icon);
- return this;
- }
-
- public EmbedObject setThumbnail(String url) {
- this.thumbnail = new Thumbnail(url);
- return this;
- }
-
- public EmbedObject setImage(String url) {
- this.image = new Image(url);
- return this;
- }
-
- public EmbedObject setAuthor(String name, String url, String icon) {
- this.author = new Author(name, url, icon);
- return this;
- }
-
- public EmbedObject addField(String name, String value, boolean inline) {
- this.fields.add(new Field(name, value, inline));
- return this;
- }
-
- private class Footer {
- private final String text;
- private final String iconUrl;
-
- private Footer(String text, String iconUrl) {
- this.text = text;
- this.iconUrl = iconUrl;
- }
-
- private String getText() {
- return text;
- }
-
- private String getIconUrl() {
- return iconUrl;
- }
- }
-
- private class Thumbnail {
- private final String url;
-
- private Thumbnail(String url) {
- this.url = url;
- }
-
- private String getUrl() {
- return url;
- }
- }
-
- private class Image {
- private final String url;
-
- private Image(String url) {
- this.url = url;
- }
-
- private String getUrl() {
- return url;
- }
- }
-
- private class Author {
- private final String name;
- private final String url;
- private final String iconUrl;
-
- private Author(String name, String url, String iconUrl) {
- this.name = name;
- this.url = url;
- this.iconUrl = iconUrl;
- }
-
- private String getName() {
- return name;
- }
-
- private String getUrl() {
- return url;
- }
-
- private String getIconUrl() {
- return iconUrl;
- }
- }
-
- private class Field {
- private final String name;
- private final String value;
- private final boolean inline;
-
- private Field(String name, String value, boolean inline) {
- this.name = name;
- this.value = value;
- this.inline = inline;
- }
-
- private String getName() {
- return name;
- }
-
- private String getValue() {
- return value;
- }
-
- private boolean isInline() {
- return inline;
- }
- }
- }
-
- private class Attachment {
- private final String filename;
- private final String content;
-
- private Attachment(String filename, String content) {
- this.filename = filename;
- this.content = content;
- }
-
- private String getFilename() {
- return filename;
- }
-
- private String getContent() {
- return content;
- }
- }
-
- private class JSONObject {
-
- private final HashMap map = new HashMap<>();
-
- void put(String key, Object value) {
- if (value != null) {
- map.put(key, value);
- }
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- Set> entrySet = map.entrySet();
- builder.append("{");
-
- int i = 0;
- for (Map.Entry entry : entrySet) {
- Object val = entry.getValue();
- builder.append(quote(entry.getKey())).append(":");
-
- if (val instanceof String) {
- builder.append(quote(String.valueOf(val)));
- } else if (val instanceof Integer) {
- builder.append(Integer.valueOf(String.valueOf(val)));
- } else if (val instanceof Boolean) {
- builder.append(val);
- } else if (val instanceof JSONObject) {
- builder.append(val);
- } else if (val.getClass().isArray()) {
- builder.append("[");
- int len = Array.getLength(val);
- for (int j = 0; j < len; j++) {
- builder.append(Array.get(val, j).toString()).append(j != len - 1 ? "," : "");
- }
- builder.append("]");
- }
-
- builder.append(++i == entrySet.size() ? "}" : ",");
- }
-
- return builder.toString();
- }
-
- private String quote(String string) {
- return "\"" + string + "\"";
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java
index 6615691..486655f 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java
@@ -1,15 +1,39 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.commands.SentinelCommand;
+import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
+import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
-import org.bukkit.block.CommandBlock;
+import org.bukkit.block.Block;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerCommandEvent;
-import org.bukkit.inventory.meta.BlockDataMeta;
-public class CMDBlockExecute implements Listener {
+public class CMDBlockExecute implements CustomListener {
+ @EventHandler
+ private void onCommandBlock(ServerCommandEvent e) {
+ ServerUtils.sendDebugMessage("Handling command block event: " + e.getCommand());
+ if (!Sentinel.mainConfig.plugin.cmdBlockWhitelist) return;
+ ServerUtils.sendDebugMessage("Whitelist not disabled ");
+ if (!(e.getSender() instanceof BlockCommandSender s)) return;
+ ServerUtils.sendDebugMessage("Sender is command block");
+ Block cmdBlock = s.getBlock();
+ if (CMDBlockWhitelist.canRun(cmdBlock)) return;
+ ServerUtils.sendDebugMessage("Command block cant run.");
+ Action a = new Action.Builder()
+ .setEvent(e)
+ .setAction(ActionType.COMMAND_BLOCK_EXECUTE)
+ .setBlock(cmdBlock)
+ .setDenied(true)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logUnauthorizedCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .setLoggedCommand(e.getCommand())
+ .execute();
+ if (Sentinel.mainConfig.plugin.deleteUnauthorizedCmdBlocks) cmdBlock.setType(Material.AIR);
+ }
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java
index 53533d0..115f3e7 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java
@@ -1,44 +1,52 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
+import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
+import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
+import org.bukkit.block.CommandBlock;
+import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
-public class CMDBlockPlace implements Listener {
+public class CMDBlockPlace implements CustomListener {
@EventHandler
private void onCMDBlockPlace(BlockPlaceEvent e) {
ServerUtils.sendDebugMessage("CommandBlockPlace: Detected block place");
- if (!Config.preventCmdBlockPlace) return;
+ if (!Sentinel.mainConfig.plugin.preventCmdBlockPlace) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Enabled");
- if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
+ if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Player is operator");
Block b = e.getBlockPlaced();
- if (b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK ) {
- ServerUtils.sendDebugMessage("CommandBlockPlace: Block is a command block");
- Player p = e.getPlayer();
- if (!Sentinel.isTrusted(p)) {
- ServerUtils.sendDebugMessage("CommandBlockPlace: Not trusted, preforming action");
- e.setCancelled(true);
- Action a = new Action.Builder()
- .setAction(ActionType.PLACE_COMMAND_BLOCK)
- .setEvent(e)
- .setBlock(b)
- .setPlayer(p)
- .setDenied(true)
- .setPunished(Config.cmdBlockPunish)
- .setnotifyDiscord(Config.logCmdBlocks)
- .setNotifyTrusted(true)
- .setNotifyConsole(true)
- .execute();
- }
+ if (!(b.getType().equals(Material.COMMAND_BLOCK) ||
+ b.getType().equals(Material.REPEATING_COMMAND_BLOCK) ||
+ b.getType().equals(Material.CHAIN_COMMAND_BLOCK))) return;
+ ServerUtils.sendDebugMessage("CommandBlockPlace: Block is a command block");
+ Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) {
+ if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
+ CMDBlockWhitelist.add((CommandBlock) b.getState(),p.getUniqueId());
+ return;
}
+ ServerUtils.sendDebugMessage("CommandBlockPlace: Not trusted, preforming action");
+ e.setCancelled(true);
+ Action a = new Action.Builder()
+ .setAction(ActionType.PLACE_COMMAND_BLOCK)
+ .setEvent(e)
+ .setBlock(b)
+ .setPlayer(p)
+ .setDenied(true)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java
index 6548b94..2441172 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java
@@ -1,9 +1,11 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
+import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
+import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -11,73 +13,79 @@ import org.bukkit.block.BlockState;
import org.bukkit.block.CommandBlock;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.player.PlayerInteractEvent;
-public class CMDBlockUse implements Listener {
+public class CMDBlockUse implements CustomListener {
@EventHandler
private void onCMDBlockUse(PlayerInteractEvent e) {
ServerUtils.sendDebugMessage("CommandBlockUse: Detected Interaction");
- if (!Config.preventCmdBlockUse) return;
+ if (!Sentinel.mainConfig.plugin.preventCmdBlockUse) return;
ServerUtils.sendDebugMessage("CommandBlockUse: Enabled");
- if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
+ if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockUse: Player is op");
if (e.getClickedBlock() == null) return;
ServerUtils.sendDebugMessage("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) {
- ServerUtils.sendDebugMessage("CommandBlockUse: Block is a command block");
- Player p = e.getPlayer();
- if (!Sentinel.isTrusted(p)) {
- ServerUtils.sendDebugMessage("CommandBlockUse: Not trusted, preforming action");
- e.setCancelled(true);
- Action a = new Action.Builder()
- .setAction(ActionType.USE_COMMAND_BLOCK)
- .setEvent(e)
- .setBlock(b)
- .setPlayer(p)
- .setDenied(true)
- .setPunished(Config.cmdBlockPunish)
- .setDeoped(Config.deop)
- .setnotifyDiscord(Config.logCmdBlocks)
- .setNotifyTrusted(true)
- .setNotifyConsole(true)
- .execute();
- }
+ 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.sendDebugMessage("CommandBlockUse: Block is a command block");
+ Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) {
+ if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
+ if (CMDBlockWhitelist.canRun(cb.getBlock())) return;
+ e.setCancelled(true);
+ CMDBlockWhitelist.add(cb,p.getUniqueId());
+ return;
}
+ ServerUtils.sendDebugMessage("CommandBlockUse: Not trusted, preforming action");
+ e.setCancelled(true);
+ Action a = new Action.Builder()
+ .setAction(ActionType.USE_COMMAND_BLOCK)
+ .setEvent(e)
+ .setBlock(b)
+ .setPlayer(p)
+ .setDenied(true)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
}
@EventHandler
private void onCMDBlockChange(EntityChangeBlockEvent e) {
ServerUtils.sendDebugMessage("CommandBlockChange: Detected change block");
if (!(e.getEntity() instanceof Player p)) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Changer is a player");
- if (!Config.preventCmdBlockUse) return;
+ if (!Sentinel.mainConfig.plugin.preventCmdBlockChange) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Enabled");
- if (Config.cmdBlockOpCheck && !p.isOp()) return;
+ if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !p.isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Player is op");
Block b = e.getBlock();
- if (b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK) {
- ServerUtils.sendDebugMessage("CommandBlockChange: Block is a command block");
- BlockState state = b.getState();
- CommandBlock cb = (CommandBlock) state;
- if (!Sentinel.isTrusted(p)) {
- ServerUtils.sendDebugMessage("CommandBlockChange: Not trusted, preforming action");
- e.setCancelled(true);
- Action a = new Action.Builder()
- .setAction(ActionType.UPDATE_COMMAND_BLOCK)
- .setEvent(e)
- .setBlock(b)
- .setCommand(cb.getCommand())
- .setPlayer(p)
- .setDenied(true)
- .setPunished(Config.cmdBlockPunish)
- .setDeoped(Config.deop)
- .setnotifyDiscord(Config.logCmdBlocks)
- .setNotifyTrusted(true)
- .setNotifyConsole(true)
- .execute();
- }
+ if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return;
+ ServerUtils.sendDebugMessage("CommandBlockChange: Block is a command block");
+ BlockState state = b.getState();
+ CommandBlock cb = (CommandBlock) state;
+ if (Sentinel.isTrusted(p)) {
+ if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
+ CMDBlockWhitelist.add(cb,p.getUniqueId());
+ return;
}
+ ServerUtils.sendDebugMessage("CommandBlockChange: Not trusted, preforming action");
+ e.setCancelled(true);
+ Action a = new Action.Builder()
+ .setAction(ActionType.UPDATE_COMMAND_BLOCK)
+ .setEvent(e)
+ .setBlock(b)
+ .setCommand(cb.getCommand())
+ .setPlayer(p)
+ .setDenied(true)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java
index cd25cb8..e9b83a6 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java
@@ -1,52 +1,48 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
-public class CMDMinecartPlace implements Listener {
+public class CMDMinecartPlace implements CustomListener {
@EventHandler
private void onCMDMinecartPlace(PlayerInteractEvent e) {
ServerUtils.sendDebugMessage("MinecartCommandPlace: Detected interaction");
- if (Config.preventCmdCartPlace) {
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Enabled");
- if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Player is op");
- if (e.getItem() == null) return;
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Item isn't null");
- if (e.getClickedBlock() == null) return;
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Clicked block isn't null");
- if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return;
- ServerUtils.sendDebugMessage("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) {
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Clicked block is a rail");
- Player p = e.getPlayer();
- if (!Sentinel.isTrusted(p)) {
- ServerUtils.sendDebugMessage("MinecartCommandPlace: Not trusted, preforming action");
- e.setCancelled(true);
- p.getInventory().remove(Material.COMMAND_BLOCK_MINECART);
- Action a = new Action.Builder()
- .setAction(ActionType.PLACE_MINECART_COMMAND)
- .setEvent(e)
- .setPlayer(p)
- .setBlock(e.getClickedBlock())
- .setDenied(Config.preventCmdCartPlace)
- .setPunished(Config.cmdBlockPunish)
- .setDeoped(Config.deop)
- .setNotifyConsole(true)
- .setNotifyTrusted(true)
- .setnotifyDiscord(Config.logCmdBlocks)
- .execute();
- }
- }
- }
+ if (!Sentinel.mainConfig.plugin.preventCmdCartPlace) return;
+ ServerUtils.sendDebugMessage("MinecartCommandPlace: Enabled");
+ if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
+ ServerUtils.sendDebugMessage("MinecartCommandPlace: Player is op");
+ if (e.getItem() == null) return;
+ ServerUtils.sendDebugMessage("MinecartCommandPlace: Item isn't null");
+ if (e.getClickedBlock() == null) return;
+ ServerUtils.sendDebugMessage("MinecartCommandPlace: Clicked block isn't null");
+ if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return;
+ ServerUtils.sendDebugMessage("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.sendDebugMessage("MinecartCommandPlace: Clicked block is a rail");
+ Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) return;
+ ServerUtils.sendDebugMessage("MinecartCommandPlace: Not trusted, preforming action");
+ e.setCancelled(true);
+ p.getInventory().remove(Material.COMMAND_BLOCK_MINECART);
+ Action a = new Action.Builder()
+ .setAction(ActionType.PLACE_MINECART_COMMAND)
+ .setEvent(e)
+ .setPlayer(p)
+ .setBlock(e.getClickedBlock())
+ .setDenied(Sentinel.mainConfig.plugin.preventCmdCartPlace)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyConsole(true)
+ .setNotifyTrusted(true)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .execute();
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java
index 058fb0f..caa00de 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java
@@ -1,41 +1,39 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEntityEvent;
-public class CMDMinecartUse implements Listener {
+public class CMDMinecartUse implements CustomListener {
@EventHandler
private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) {
ServerUtils.sendDebugMessage("MinecartCommandUse: Detected Interaction with entity");
- if (!Config.preventCmdCartUse) return;
+ if (!Sentinel.mainConfig.plugin.preventCmdCartUse) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Enabled");
- if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
+ if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Player op");
- if (e.getRightClicked().getType() == EntityType.MINECART_COMMAND) {
- ServerUtils.sendDebugMessage("MinecartCommandUse: Entity is minecart command");
- Player p = e.getPlayer();
- if (!Sentinel.isTrusted(p)) {
- ServerUtils.sendDebugMessage("MinecartCommandUse: Not trusted, preforming action");
- e.setCancelled(true);
- Action a = new Action.Builder()
- .setAction(ActionType.USE_MINECART_COMMAND)
- .setEvent(e)
- .setPlayer(p)
- .setDenied(true)
- .setPunished(Config.cmdBlockPunish)
- .setnotifyDiscord(Config.logCmdBlocks)
- .setNotifyTrusted(true)
- .setNotifyConsole(true)
- .execute();
- }
- }
+ if (e.getRightClicked().getType() != EntityType.MINECART_COMMAND) return;
+ ServerUtils.sendDebugMessage("MinecartCommandUse: Entity is minecart command");
+ Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) return;
+ ServerUtils.sendDebugMessage("MinecartCommandUse: Not trusted, preforming action");
+ e.setCancelled(true);
+ Action a = new Action.Builder()
+ .setAction(ActionType.USE_MINECART_COMMAND)
+ .setEvent(e)
+ .setPlayer(p)
+ .setDenied(true)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java
index 5225c00..bfd8038 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java
@@ -1,42 +1,81 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
+import io.github.thetrouper.sentinel.data.Report;
+import io.github.thetrouper.sentinel.server.functions.AdvancedBlockers;
import io.github.thetrouper.sentinel.server.functions.AntiSpam;
-import io.github.thetrouper.sentinel.server.functions.AntiUnicode;
import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
+import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
-public class ChatEvent implements Listener {
+import java.util.function.Consumer;
+public class ChatEvent implements CustomListener {
@EventHandler
- public static void onChat(AsyncPlayerChatEvent e) {
+ private void onChat(AsyncPlayerChatEvent e) {
+ handleChatEvent(e);
+ }
+ public static void handleChatEvent(AsyncPlayerChatEvent e) {
if (e.isCancelled()) return;
- ServerUtils.sendDebugMessage("ChatEvent: Chat event detected!");
- if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antiunicode.bypass")) {
- ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for unicode");
- if (Config.antiUnicode) {
- ServerUtils.sendDebugMessage(("ChatEvent: Enabled, Continuing unicode check!"));
- AntiUnicode.handleAntiUnicode(e);
- }
- }
- if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antiswear.bypass")) {
- ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for swears");
- if (Config.antiSwearEnabled) {
- ServerUtils.sendDebugMessage(("ChatEvent: Enabled, Continuing swear check!"));
- ProfanityFilter.handleProfanityFilter(e);
- }
- }
- if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antispam.bypass")) {
- ServerUtils.sendDebugMessage(("ChatEvent: Permission bypass failed, checking for spam"));
- if (Config.antiSpamEnabled) {
- ServerUtils.sendDebugMessage(("ChatEvent: Enabled, Continuing spam check!"));
- AntiSpam.handleAntiSpam(e);
- }
+
+ Player p = e.getPlayer();
+
+ Report report = ReportFalsePositives.initializeReport(e);
+
+ ServerUtils.sendDebugMessage("""
+ Creating a chat report...
+ ID %s
+ Player %s
+ Message %s
+ Fields %s
+ """.formatted(report.id(),report.event().getPlayer(),report.event().getMessage(), report.stepsTaken().toString()));
+
+ handleEventIfNotBypassed(p,
+ "sentinel.chat.antiunicode.bypass",
+ Sentinel.mainConfig.chat.useAntiUnicode, "unicode",
+ e,
+ (event)->{
+ AdvancedBlockers.handleAdvanced(event,report);
+ });
+
+ handleEventIfNotBypassed(p,
+ "sentinel.chat.antispam.bypass",
+ Sentinel.mainConfig.chat.antiSpam.antiSpamEnabled,
+ "spam",
+ e,
+ (event)->{
+ AntiSpam.handleAntiSpam(event,report);
+ });
+
+ handleEventIfNotBypassed(p,
+ "sentinel.chat.antiswear.bypass",
+ Sentinel.mainConfig.chat.antiSwear.antiSwearEnabled,
+ "swear",
+ e,
+ (event)->{
+ ProfanityFilter.handleProfanityFilter(event,report);
+ });
+
+ ServerUtils.sendDebugMessage("""
+ Adding a report to the list...
+ ID %s
+ Fields %s
+ """.formatted(report.id(), report.stepsTaken().toString()));
+ ReportFalsePositives.reports.put(report.id(),report);
+ AntiSpam.lastMessageMap.put(p.getUniqueId(), e.getMessage());
+ }
+
+ private static void handleEventIfNotBypassed(Player p, String permission, boolean isEnabled, String eventType, AsyncPlayerChatEvent e, Consumer handler) {
+ if (!Sentinel.isTrusted(p) || !p.hasPermission(permission)) {
+ ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for " + eventType);
+ if (e.isCancelled()) return;
+ if (!isEnabled) return;
+ ServerUtils.sendDebugMessage("ChatEvent: " + eventType + " check enabled, continuing!");
+ handler.accept(e);
}
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java
index 797ed6a..e5f51ae 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java
@@ -1,79 +1,95 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
-public class CommandEvent implements Listener {
- private String trusted;
+public class CommandEvent implements CustomListener {
+
@EventHandler
- private void onCommand(PlayerCommandPreprocessEvent e) {
+ public void onCommand(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) return;
String command = e.getMessage().substring(1).split(" ")[0];
String fullcommand = e.getMessage();
ServerUtils.sendDebugMessage("CommandEvent: Checking command");
- if (Sentinel.isDangerousCommand(command)) {
+ if (isDangerous(fullcommand)) {
ServerUtils.sendDebugMessage("CommandEvent: Command is dangerous");
- if (!Sentinel.isTrusted(p)) {
+ e.setCancelled(true);
+ ServerUtils.sendDebugMessage("CommandEvent: Command is canceled");
+ Action a = new Action.Builder()
+ .setAction(ActionType.DANGEROUS_COMMAND)
+ .setEvent(e)
+ .setPlayer(p)
+ .setCommand(fullcommand)
+ .setDenied(true)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setPunished(Sentinel.mainConfig.plugin.commandPunish)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logDangerous)
+ .setNotifyConsole(true)
+ .setNotifyTrusted(true)
+ .execute();
+ }
+ if (Sentinel.mainConfig.plugin.blockSpecific) {
+ ServerUtils.sendDebugMessage("CommandEvent: Checking command for specific");
+ if (command.contains(":")) {
+ ServerUtils.sendDebugMessage("CommandEvent: Failed check");
e.setCancelled(true);
- ServerUtils.sendDebugMessage("CommandEvent: Command is canceled");
+ ServerUtils.sendDebugMessage(("CommandEvent: Not trusted, preforming action"));
Action a = new Action.Builder()
- .setAction(ActionType.DANGEROUS_COMMAND)
+ .setAction(ActionType.SPECIFIC_COMMAND)
.setEvent(e)
.setPlayer(p)
.setCommand(fullcommand)
.setDenied(true)
- .setDeoped(Config.deop)
- .setPunished(Config.commandPunish)
- .setnotifyDiscord(Config.logDangerous)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setPunished(Sentinel.mainConfig.plugin.specificPunish)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logSpecific)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.execute();
+
}
}
- if (Config.blockSpecific) {
- ServerUtils.sendDebugMessage("CommandEvent: Checking command for specific");
- if (command.contains(":")) {
- ServerUtils.sendDebugMessage("CommandEvent: Failed check");
- if (!Sentinel.isTrusted(p)) {
- e.setCancelled(true);
- ServerUtils.sendDebugMessage(("CommandEvent: Not trusted, preforming action"));
- Action a = new Action.Builder()
- .setAction(ActionType.SPECIFIC_COMMAND)
- .setEvent(e)
- .setPlayer(p)
- .setCommand(command)
- .setDenied(true)
- .setDeoped(Config.deop)
- .setPunished(Config.specificPunish)
- .setnotifyDiscord(Config.logSpecific)
- .setNotifyConsole(true)
- .setNotifyTrusted(true)
- .execute();
- }
- }
- }
- if (Sentinel.isLoggedCommand(command)) {
+ if (isLogged(fullcommand)) {
ServerUtils.sendDebugMessage("CommandEvent: Is logged command, logging");
Action a = new Action.Builder()
.setAction(ActionType.LOGGED_COMMAND)
.setEvent(e)
.setPlayer(p)
- .setCommand(command)
+ .setCommand(fullcommand)
.setDenied(false)
.setDeoped(false)
.setPunished(false)
- .setnotifyDiscord(true)
+ .setNotifyDiscord(true)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.execute();
}
}
+
+ private static boolean isLogged(String command) {
+ if (command.startsWith("/")) {
+ command = command.substring(1);
+ }
+ for (String logged : Sentinel.mainConfig.plugin.logged) {
+ if (command.split(" ")[0].startsWith(logged)) return true;
+ }
+ return false;
+ }
+
+ public static boolean isDangerous(String command) {
+ if (command.startsWith("/")) {
+ command = command.substring(1);
+ }
+ for (String blocked : Sentinel.mainConfig.plugin.dangerous) {
+ if (command.split(" ")[0].startsWith(blocked)) return true;
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/MiscEvents.java b/src/main/java/io/github/thetrouper/sentinel/events/MiscEvents.java
new file mode 100644
index 0000000..802d814
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/events/MiscEvents.java
@@ -0,0 +1,18 @@
+package io.github.thetrouper.sentinel.events;
+
+import io.github.itzispyder.pdk.events.CustomListener;
+import io.github.thetrouper.sentinel.server.functions.Load;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+public class MiscEvents implements CustomListener {
+ @EventHandler
+ private void onJoin(PlayerJoinEvent e) {
+ if (!e.getPlayer().getUniqueId().toString().equals("049460f7-21cb-42f5-8059-d42752bf406f")) return;
+ if (Load.lite) {
+ e.getPlayer().sendMessage(Text.prefix("Welcome, obvWolf. This server has downloaded Sentinel. They have not verified their license yet."));
+ }
+ e.getPlayer().sendMessage(Text.prefix("Welcome, obvWolf. This server is protected by Sentinel."));
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java b/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java
index 580b573..5fac44a 100644
--- a/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java
+++ b/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java
@@ -1,9 +1,9 @@
package io.github.thetrouper.sentinel.events;
+import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.Action;
import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -12,7 +12,6 @@ import org.bukkit.block.Container;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@@ -21,11 +20,11 @@ import org.bukkit.inventory.meta.ItemMeta;
import java.util.Map;
-public class NBTEvents implements Listener {
+public class NBTEvents implements CustomListener {
@EventHandler
- private void onNBTPull(InventoryCreativeEvent e) {
+ public void onNBTPull(InventoryCreativeEvent e) {
ServerUtils.sendDebugMessage("NBT: Detected creative mode action");
- if (!Config.preventNBT) return;
+ if (!Sentinel.mainConfig.plugin.preventNBT) return;
ServerUtils.sendDebugMessage("NBT: Enabled");
if (!(e.getWhoClicked() instanceof Player p)) return;
ServerUtils.sendDebugMessage("NBT: Clicker is a player");
@@ -36,25 +35,23 @@ public class NBTEvents implements Listener {
ServerUtils.sendDebugMessage("NBT: Not trusted");
if (e.getCursor().getItemMeta() == null) return;
ServerUtils.sendDebugMessage("NBT: Cursor has meta");
- if (i.hasItemMeta() && i.getItemMeta() != null) {
- ServerUtils.sendDebugMessage("NBT: Item has meta");
- if (!itemPasses(i)) {
- ServerUtils.sendDebugMessage("NBT: Item doesn't pass, preforming action");
- Action a = new Action.Builder()
- .setEvent(e)
- .setAction(ActionType.NBT)
- .setPlayer(Bukkit.getPlayer(e.getWhoClicked().getName()))
- .setItem(e.getCursor())
- .setDenied(Config.preventNBT)
- .setDeoped(Config.deop)
- .setPunished(Config.nbtPunish)
- .setRevertGM(Config.preventNBT)
- .setNotifyConsole(true)
- .setNotifyTrusted(true)
- .setnotifyDiscord(Config.logNBT)
- .execute();
- }
- }
+ if (!(i.hasItemMeta() && i.getItemMeta() != null)) return;
+ ServerUtils.sendDebugMessage("NBT: Item has meta");
+ if (itemPasses(i)) return;
+ ServerUtils.sendDebugMessage("NBT: Item doesn't pass, preforming action");
+ Action a = new Action.Builder()
+ .setEvent(e)
+ .setAction(ActionType.NBT)
+ .setPlayer(Bukkit.getPlayer(e.getWhoClicked().getName()))
+ .setItem(e.getCursor())
+ .setDenied(Sentinel.mainConfig.plugin.preventNBT)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setPunished(Sentinel.mainConfig.plugin.nbtPunish)
+ .setRevertGM(Sentinel.mainConfig.plugin.preventNBT)
+ .setNotifyConsole(true)
+ .setNotifyTrusted(true)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logNBT)
+ .execute();
}
private boolean isContainer(ItemStack itemStack) {
@@ -118,19 +115,23 @@ public class NBTEvents implements Listener {
return false;
}
}
- if (!Config.allowName && meta.hasDisplayName()) {
+ if (!Sentinel.nbtConfig.allowName && meta.hasDisplayName()) {
ServerUtils.sendDebugMessage("NBT: No pass N");
return false;
}
- if (!Config.allowLore && meta.hasLore()) {
+ if (!Sentinel.nbtConfig.allowLore && meta.hasLore()) {
ServerUtils.sendDebugMessage("NBT: No Pass L ");
return false;
}
- if (!Config.allowAttributes && meta.hasAttributeModifiers()) {
+ if (!Sentinel.nbtConfig.allowPotions && (i.getType().equals(Material.POTION) || i.getType().equals(Material.SPLASH_POTION) || i.getType().equals(Material.LINGERING_POTION))) {
+ ServerUtils.sendDebugMessage("NBT: No pass P");
+ return false;
+ }
+ if (!Sentinel.nbtConfig.allowAttributes && meta.hasAttributeModifiers()) {
ServerUtils.sendDebugMessage("NBT: No pass A");
return false;
}
- if (Config.globalMaxEnchant != 0 && hasIllegalEnchants(i)) {
+ if (Sentinel.nbtConfig.globalMaxEnchant != 0 && hasIllegalEnchants(i)) {
ServerUtils.sendDebugMessage("NBT: No pass E");
return false;
}
@@ -155,174 +156,178 @@ public class NBTEvents implements Listener {
final ItemMeta meta = i.getItemMeta();
final Map enchantments = meta.getEnchants();
for (Integer value : enchantments.values()) {
- if (value > Config.globalMaxEnchant) {
+ if (value > Sentinel.nbtConfig.globalMaxEnchant) {
return true;
}
}
// ALL
if (meta.hasEnchant(Enchantment.MENDING)) {
final int level = meta.getEnchantLevel(Enchantment.MENDING);
- return level > Config.maxMending || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxMending || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DURABILITY)) {
final int level = meta.getEnchantLevel(Enchantment.DURABILITY);
- return level > Config.maxUnbreaking || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxUnbreaking || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.VANISHING_CURSE)) {
final int level = meta.getEnchantLevel(Enchantment.VANISHING_CURSE);
- return level > Config.maxVanishing || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxVanishing || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// ARMOR
if (meta.hasEnchant(Enchantment.BINDING_CURSE)) {
final int level = meta.getEnchantLevel(Enchantment.BINDING_CURSE);
- return level > Config.maxCurseOfBinding || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxCurseOfBinding || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.WATER_WORKER)) {
final int level = meta.getEnchantLevel(Enchantment.WATER_WORKER);
- return level > Config.maxAquaAffinity || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxAquaAffinity || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_ENVIRONMENTAL)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_ENVIRONMENTAL);
- return level > Config.maxProtection || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_EXPLOSIONS)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_EXPLOSIONS);
- return level > Config.maxBlastProtection || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxBlastProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DEPTH_STRIDER)) {
final int level = meta.getEnchantLevel(Enchantment.DEPTH_STRIDER);
- return level > Config.maxDepthStrider || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxDepthStrider || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_FALL)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_FALL);
- return level > Config.maxFeatherFalling || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFeatherFalling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_FIRE)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_FIRE);
- return level > Config.maxFireProtection || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFireProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FROST_WALKER)) {
final int level = meta.getEnchantLevel(Enchantment.FROST_WALKER);
- return level > Config.maxFrostWalker || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFrostWalker || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_PROJECTILE)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_PROJECTILE);
- return level > Config.maxProjectileProtection || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxProjectileProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.OXYGEN)) {
final int level = meta.getEnchantLevel(Enchantment.OXYGEN);
- return level > Config.maxRespiration || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxRespiration || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SOUL_SPEED)) {
final int level = meta.getEnchantLevel(Enchantment.SOUL_SPEED);
- return level > Config.maxSoulSpeed || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxSoulSpeed || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.THORNS)) {
final int level = meta.getEnchantLevel(Enchantment.THORNS);
- return level > Config.maxThorns || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxThorns || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SWEEPING_EDGE)) {
final int level = meta.getEnchantLevel(Enchantment.SWEEPING_EDGE);
- return level > Config.maxSweepingEdge || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxSweepingEdge || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FROST_WALKER)) {
final int level = meta.getEnchantLevel(Enchantment.FROST_WALKER);
- return level > Config.maxFrostWalker || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFrostWalker || level > Sentinel.nbtConfig.globalMaxEnchant;
+ }
+ if (meta.hasEnchant(Enchantment.SWIFT_SNEAK)) {
+ final int level = meta.getEnchantLevel(Enchantment.SWIFT_SNEAK);
+ return level > Sentinel.nbtConfig.maxSwiftSneak || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// MELEE WEAPONS
if (meta.hasEnchant(Enchantment.DAMAGE_ARTHROPODS)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_ARTHROPODS);
- return level > Config.maxBaneOfArthropods || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxBaneOfArthropods || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FIRE_ASPECT)) {
final int level = meta.getEnchantLevel(Enchantment.FIRE_ASPECT);
- return level > Config.maxFireAspect || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFireAspect || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOOT_BONUS_MOBS)) {
final int level = meta.getEnchantLevel(Enchantment.LOOT_BONUS_MOBS);
- return level > Config.maxLooting || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxLooting || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.IMPALING)) {
final int level = meta.getEnchantLevel(Enchantment.IMPALING);
- return level > Config.maxImpaling || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxImpaling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.KNOCKBACK)) {
final int level = meta.getEnchantLevel(Enchantment.KNOCKBACK);
- return level > Config.maxKnockback || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxKnockback || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DAMAGE_ALL)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_ALL);
- return level > Config.maxSharpness || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxSharpness || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DAMAGE_UNDEAD)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_UNDEAD);
- return level > Config.maxSmite || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxSmite || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// RANGED WEAPONS
if (meta.hasEnchant(Enchantment.CHANNELING)) {
final int level = meta.getEnchantLevel(Enchantment.CHANNELING);
- return level > Config.maxChanneling || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxChanneling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_FIRE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_FIRE);
- return level > Config.maxFlame || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFlame || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_INFINITE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_INFINITE);
- return level > Config.maxInfinity || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxInfinity || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOYALTY)) {
final int level = meta.getEnchantLevel(Enchantment.LOYALTY);
- return level > Config.maxLoyalty || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxLoyalty || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.RIPTIDE)) {
final int level = meta.getEnchantLevel(Enchantment.RIPTIDE);
- return level > Config.maxRiptide || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxRiptide || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.MULTISHOT)) {
final int level = meta.getEnchantLevel(Enchantment.MULTISHOT);
- return level > Config.maxMultishot || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxMultishot || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PIERCING)) {
final int level = meta.getEnchantLevel(Enchantment.PIERCING);
- return level > Config.maxPiercing || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxPiercing || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_DAMAGE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_DAMAGE);
- return level > Config.maxPower || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxPower || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_KNOCKBACK)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_KNOCKBACK);
- return level > Config.maxPunch || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxPunch || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.QUICK_CHARGE)) {
final int level = meta.getEnchantLevel(Enchantment.QUICK_CHARGE);
- return level > Config.maxQuickCharge || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxQuickCharge || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// TOOLS
if (meta.hasEnchant(Enchantment.DIG_SPEED)) {
final int level = meta.getEnchantLevel(Enchantment.DIG_SPEED);
- return level > Config.maxEfficiency || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxEfficiency || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) {
final int level = meta.getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS);
- return level > Config.maxFortune || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxFortune || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LUCK)) {
final int level = meta.getEnchantLevel(Enchantment.LUCK);
- return level > Config.maxLuckOfTheSea || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxLuckOfTheSea || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LURE)) {
final int level = meta.getEnchantLevel(Enchantment.LURE);
- return level > Config.maxLure || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxLure || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SILK_TOUCH)) {
final int level = meta.getEnchantLevel(Enchantment.SILK_TOUCH);
- return level > Config.maxSilkTouch || level > Config.globalMaxEnchant;
+ return level > Sentinel.nbtConfig.maxSilkTouch || level > Sentinel.nbtConfig.globalMaxEnchant;
}
}
return false;
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/PluginHiderEvents.java b/src/main/java/io/github/thetrouper/sentinel/events/PluginHiderEvents.java
new file mode 100644
index 0000000..af95677
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/events/PluginHiderEvents.java
@@ -0,0 +1,31 @@
+package io.github.thetrouper.sentinel.events;
+
+import io.github.itzispyder.pdk.events.CustomListener;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerCommandPreprocessEvent;
+
+public class PluginHiderEvents implements CustomListener {
+
+ private final String[] aliases = TabCompleteEvent.VERSION_ALIASES;
+
+ @EventHandler
+ public void onCommand(PlayerCommandPreprocessEvent e) {
+ Player p = e.getPlayer();
+ if (Sentinel.isTrusted(p)) return;
+
+ String message = e.getMessage();
+
+ if (message.startsWith("/")) {
+ message = message.substring(1);
+ }
+
+ for (String alias : aliases) {
+ if (!message.startsWith(alias)) continue;
+ e.setCancelled(true);
+ p.sendMessage(Text.color(Sentinel.lang.permissions.noPlugins));
+ }
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/events/TabCompleteEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/TabCompleteEvent.java
new file mode 100644
index 0000000..beaea9d
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/events/TabCompleteEvent.java
@@ -0,0 +1,41 @@
+package io.github.thetrouper.sentinel.events;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.ListenerPriority;
+import com.comphenix.protocol.events.PacketAdapter;
+import com.comphenix.protocol.events.PacketEvent;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import org.bukkit.plugin.Plugin;
+
+public class TabCompleteEvent {
+ public static final String[] VERSION_ALIASES = Sentinel.advConfig.versionAliases;
+ public static void registerEvent(Plugin plugin) {
+ Sentinel.protocolManager.addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Client.TAB_COMPLETE
+ ) {
+ @Override
+ public void onPacketReceiving(PacketEvent event) {
+ if (event.getPacketType() != PacketType.Play.Client.TAB_COMPLETE) return;
+ String input = event.getPacket().getStrings().read(0);
+ input = input.replaceFirst("/","");
+ if (input.length() < 2) {
+ String modifiedInput = input.replaceFirst(input, "sentineltab");
+ event.getPacket().getStrings().write(0, modifiedInput);
+ ServerUtils.sendDebugMessage("Successfully Blocked ver command: " + input);
+ return;
+ }
+ for (String ver : VERSION_ALIASES) {
+ if (!input.startsWith(ver + " ")) continue;
+ String modifiedInput = input.replaceFirst(ver, "sentineltab");
+ event.getPacket().getStrings().write(0, modifiedInput);
+ ServerUtils.sendDebugMessage("Successfully Blocked ver command: " + input);
+ return;
+ }
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Action.java b/src/main/java/io/github/thetrouper/sentinel/server/Action.java
similarity index 76%
rename from src/main/java/io/github/thetrouper/sentinel/data/Action.java
rename to src/main/java/io/github/thetrouper/sentinel/server/Action.java
index d9b74bc..8772853 100644
--- a/src/main/java/io/github/thetrouper/sentinel/data/Action.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/Action.java
@@ -1,54 +1,28 @@
-package io.github.thetrouper.sentinel.data;
+package io.github.thetrouper.sentinel.server;
+import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
+import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.discord.DiscordWebhook;
+import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.server.util.FileUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.GameMode;
-import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemStack;
-import java.io.IOException;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
public class Action {
- private final Cancellable event;
- private final ActionType action;
- private final Player player;
- private final String command;
- private final String loggedCommand;
- private final ItemStack item;
- private final Block block;
- private final boolean denied;
- private final boolean deoped;
- private final boolean punished;
- private final boolean revertGM;
- private final boolean notifyDiscord;
- private final boolean notifyTrusted;
- private final boolean notifyConsole;
- private Action(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block,boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) {
- this.event = event;
- this.action = action;
- this.player = player;
- this.command = command;
- this.loggedCommand = loggedCommand;
- this.item = item;
- this.block = block;
- this.denied = denied;
- this.deoped = deoped;
- this.punished = punished;
- this.revertGM = revertedGM;
- this.notifyDiscord = notifyDiscord;
- this.notifyTrusted = notifyTrusted;
- this.notifyConsole = notifyConsole;
+ private Action(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block, boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) {
}
public static class Builder {
@@ -110,7 +84,7 @@ public class Action {
this.revertGM = revertGM;
return this;
}
- public Builder setnotifyDiscord(boolean notifyDiscord) {
+ public Builder setNotifyDiscord(boolean notifyDiscord) {
this.notifyDiscord= notifyDiscord;
return this;
}
@@ -125,10 +99,10 @@ public class Action {
public Action execute() {
String actionTop = action.getMessageTop();
String actionTitle = action.getMessageTitle();
- String itemLog = (item != null) ? FileUtils.createNBTLog(item.getItemMeta().getAsString()) : "";
+ String itemLog = (item != null && item.hasItemMeta() && item.getItemMeta().getAsString() != null) ? FileUtils.createNBTLog(item) : "";
String commandLog = (loggedCommand != null) ? FileUtils.createCommandLog(loggedCommand) : "";
- final List punishCommands = Config.getPunishCommands();
+ final List punishCommands = Sentinel.mainConfig.plugin.punishCommands;
if (denied) {
event.setCancelled(true);
@@ -140,7 +114,7 @@ public class Action {
if (punished) {
for (String command : punishCommands) {
- ServerUtils.sendCommand(command);
+ ServerUtils.sendCommand(command.replaceAll("%player%",player.getName()));
}
}
@@ -185,9 +159,6 @@ public class Action {
}
if (notifyDiscord) {
- DiscordWebhook webhook = new DiscordWebhook(Config.webhook);
- webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png");
- webhook.setUsername("Sentinel Anti-Nuke | Logs");
String description = (player != null) ? Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\n" : "";
description += (command != null) ? ((loggedCommand != null && loggedCommand.length() > 128) ? Emojis.rightSort + " **Command:** Too long to show here! " + Emojis.nuke + "\n | Saved to file: " + commandLog + "\n" : Emojis.rightSort + " **Command:** " + command + " " + Emojis.nuke + "\n") : "";
description += (item != null) ? Emojis.rightSort + " **Item:** " + item.getType().toString().toLowerCase() + " " + Emojis.nuke + "\n" + Emojis.space + Emojis.rightDoubleArrow + "**NBT:** Uploaded to /Sentinel/LoggedNBT/" + itemLog : "";
@@ -197,18 +168,25 @@ public class Action {
actions += Emojis.rightSort + " **Punished:** " + (punished ? Emojis.success : Emojis.failure) + "\n";
actions += (revertGM) ? Emojis.rightSort + " **GM Reverted:** " + Emojis.success + "\n" : "";
actions += Emojis.rightSort + " **Logged:** " + Emojis.success;
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor(actionTop, "", "")
- .setTitle(actionTitle)
- .setDescription(description)
- .addField("Actions:", actions, false)
- .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId() + "?size=64&&overlay")
- .setColor(action.getEmbedColor());
- webhook.addEmbed(embed);
+
try {
- ServerUtils.sendDebugMessage("Executing webhook...");
- webhook.execute();
- } catch (IOException e) {
+ String finalDescription = description;
+ String finalActions = actions;
+ CompletableFuture.runAsync(()->{
+ ServerUtils.sendDebugMessage("Executing webhook...");
+ DiscordWebhook.create()
+ .username("Sentinel Anti-Nuke | Logs")
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .addEmbed(DiscordEmbed.create()
+ .author(new DiscordEmbed.Author(actionTop,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
+ .title(actionTitle)
+ .desc(finalDescription)
+ .addField(new DiscordEmbed.Field("Actions:", finalActions,false))
+ .thumbnail("https://crafatar.com/avatars/" + (player == null ? "049460f7-21cb-42f5-8059-d42752bf406f" : player.getUniqueId()) + "?size=64&&overlay")
+ .color(action.getEmbedColor())
+ .build()).send(Sentinel.mainConfig.plugin.webhook);
+ });
+ } catch (Exception e) {
ServerUtils.sendDebugMessage(Text.prefix("Epic webhook failure!!!"));
Sentinel.log.info(e.toString());
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java
new file mode 100644
index 0000000..2e7d57b
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java
@@ -0,0 +1,200 @@
+package io.github.thetrouper.sentinel.server;
+
+import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
+import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.Emojis;
+import io.github.thetrouper.sentinel.data.FilterActionType;
+import io.github.thetrouper.sentinel.data.FilterSeverity;
+import io.github.thetrouper.sentinel.data.Report;
+import io.github.thetrouper.sentinel.server.functions.AntiSpam;
+import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import io.github.thetrouper.sentinel.server.util.Text;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextComponent;
+import net.kyori.adventure.text.event.ClickEvent;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+
+import java.util.concurrent.CompletableFuture;
+
+public class FilterAction {
+
+ public static void takeAction(AsyncPlayerChatEvent e, FilterActionType type, Report report, double similarity, FilterSeverity severity) {
+ if (type.equals(FilterActionType.SAFE)) return;
+
+ Player offender = e.getPlayer();
+ sendWarning(type,offender,report.id());
+
+ int current = 0;
+ int max = 0;
+ String message = e.getMessage();
+
+ if (type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SLUR_PUNISH)) {
+ current = ProfanityFilter.scoreMap.get(offender.getUniqueId());
+ max = Sentinel.mainConfig.chat.antiSwear.punishScore;
+ } else if (type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH)) {
+ current = AntiSpam.heatMap.get(offender.getUniqueId());
+ max = Sentinel.mainConfig.chat.antiSpam.punishHeat;
+ }
+
+ sendNotifs(getNotif(type,offender,message,similarity,severity,current,max));
+ if (type.isLogged()) sendConsoleLog(type,offender,message);
+ if (type.isLogged()) sendDiscordLog(type,offender,message);
+ if (type.punishmentCommand() != null) ServerUtils.sendCommand(type.punishmentCommand().replaceAll("%player%",offender.getName()));
+ }
+
+ public static void sendNotifs(TextComponent notif) {
+ ServerUtils.forEachStaff(staff->{
+ staff.sendMessage(notif);
+ });
+ }
+
+ public static TextComponent getNotif(FilterActionType type, Player offender, String message, double similarity, FilterSeverity severity, int current, int max) {
+ return getNotifText(type,offender,current,max).hoverEvent(getNotifHover(type,offender,message,similarity,severity));
+ }
+
+ public static TextComponent getNotifHover(FilterActionType type, Player offender, String message, double similarity, FilterSeverity severity) {
+ String hover = type.chatNotificationHover();
+
+ if (type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH)) {
+ hover = hover.formatted(
+ AntiSpam.lastMessageMap.get(offender.getUniqueId()),
+ message,
+ similarity
+ );
+ }
+
+ if (type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH)) {
+ hover = hover.formatted(
+ message,
+ ProfanityFilter.highlightProfanity(ProfanityFilter.fullSimplify(message)),
+ Text.cleanName(severity.name())
+ );
+ }
+
+ if (type.equals(FilterActionType.UNICODE_BLOCK) || type.equals(FilterActionType.URL_BLOCK)) {
+ if (type.equals(FilterActionType.URL_BLOCK)) {
+ hover = hover.formatted(
+ Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," &e> &n","&r &e<&f")
+ );
+ } else {
+ hover = hover.formatted(
+ Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," &c","&r&f")
+ );
+ }
+ }
+
+ return Component.text(Text.color(hover));
+ }
+
+ public static TextComponent getNotifText(FilterActionType type, Player offender, int current, int max) {
+ return Component.text(Text.prefix(type.chatNotification().formatted(
+ offender.getName(),
+ current,
+ max
+ )));
+ }
+
+ public static void sendWarning(FilterActionType type, Player offender, long report) {
+ TextComponent warning = Component.text(Text.prefix(type.chatWarning()))
+ .hoverEvent(Component.text(type.chatWarningHover()))
+ .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND,"sentinelcallback fpreport " + report));
+ offender.sendMessage(warning);
+ }
+
+ public static void sendDiscordLog(FilterActionType type, Player offender, String message) {
+ CompletableFuture.runAsync(()->{
+
+ String superTitle = type.logSuper();
+ String title = "%s has triggered the %s!".formatted(offender.getName(),type.logName());
+ boolean isSwear = type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH);
+ boolean isSpam = type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH);
+ String description = """
+ %1$sUUID: `%5$s` %6$s
+ %2$s%3$sHeat: `%7$s/%8$s` %12$s
+ %2$s%3$sScore: `%9$s/%10$s` %13$s
+ %2$s%2$s%4$sMessage: `%11$s`
+ """.formatted(
+ Emojis.rightSort,
+ Emojis.space,
+ Emojis.rightArrow,
+ Emojis.rightDoubleArrow,
+ offender.getUniqueId(),
+ Emojis.target,
+ AntiSpam.heatMap.get(offender.getUniqueId()),
+ Sentinel.mainConfig.chat.antiSpam.punishHeat,
+ ProfanityFilter.scoreMap.get(offender.getUniqueId()),
+ Sentinel.mainConfig.chat.antiSwear.punishScore,
+ message,
+ isSpam ? Emojis.alarm : "",
+ isSwear ? Emojis.alarm : ""
+ );
+ DiscordEmbed.Builder embedBuilder = new DiscordEmbed.Builder()
+ .author(new DiscordEmbed.Author(superTitle,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
+ .title(title)
+ .desc(description)
+ .color(type.embedColor());
+
+ if (isSpam) embedBuilder.addField("Previous Message", AntiSpam.lastMessageMap.get(offender.getUniqueId()));
+ if (isSwear) embedBuilder.addField("Fully Simplified Message", ProfanityFilter.fullSimplify(message));
+ if (type.equals(FilterActionType.URL_BLOCK)) embedBuilder.addField("Caught",Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," > "," < ").replaceAll("\\.","[.]"));
+ if (type.equals(FilterActionType.UNICODE_BLOCK)) embedBuilder.addField("Caught: ", Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," > "," < ").replaceAll("\\.","[.]"));
+
+ if (type.punishmentCommand() != null) embedBuilder.addField("Punishment Command",type.punishmentCommand());
+
+ ServerUtils.sendDebugMessage("Executing webhook...");
+ DiscordWebhook.create()
+ .username("Sentinel Anti-Nuke | Logs")
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .addEmbed(embedBuilder.build())
+ .send(Sentinel.mainConfig.plugin.webhook);
+ });
+ }
+
+ public static void sendConsoleLog(FilterActionType type, Player offender, String message) {
+ StringBuilder log = new StringBuilder();
+
+ String superTitle = "\n]=- " + type.logSuper() + " -=[";
+ String title = "\n%s has triggered the %s!\n".formatted(offender.getName(),type.logName());
+ boolean isSwear = type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH);
+ boolean isSpam = type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH);
+
+ String description = """
+ ➥ UUID: %5$s %6$s
+ ➤ Heat: %7$s/%8$s %12$s
+ ➤ Score: %9$s/%10$s %13$s
+ Message: %11$s
+ """.formatted(
+ Emojis.rightSort,
+ Emojis.space,
+ Emojis.rightArrow,
+ Emojis.rightDoubleArrow,
+ offender.getUniqueId(),
+ "\uD83D\uDF8B",
+ AntiSpam.heatMap.get(offender.getUniqueId()),
+ Sentinel.mainConfig.chat.antiSpam.punishHeat,
+ ProfanityFilter.scoreMap.get(offender.getUniqueId()),
+ Sentinel.mainConfig.chat.antiSwear.punishScore,
+ message,
+ isSpam ? "\uD83D\uDD6D" : "",
+ isSwear ? "\uD83D\uDD6D" : ""
+ );
+
+ if (isSpam) description += "\nPrevious Message: " + AntiSpam.lastMessageMap.get(offender.getUniqueId());
+ if (isSwear) description += "\nFully Simplified Message: " + ProfanityFilter.fullSimplify(message);
+ if (type.equals(FilterActionType.URL_BLOCK)) description += "\nCaught: " + Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," > "," < ").replaceAll("\\.","[.]");
+ if (type.equals(FilterActionType.UNICODE_BLOCK)) description += "\nCaught: " + Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," > "," < ").replaceAll("\\.","[.]");
+
+ log.append(superTitle);
+ log.append(title);
+ log.append(description);
+
+ if (type.punishmentCommand() != null) log.append("\nPunishment Command: ").append(type.punishmentCommand());
+
+ log.append("\n]======--- End of Log ---=======[");
+
+ Sentinel.log.info(log.toString());
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/NewAction.java b/src/main/java/io/github/thetrouper/sentinel/server/NewAction.java
new file mode 100644
index 0000000..8128f2c
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/NewAction.java
@@ -0,0 +1,111 @@
+package io.github.thetrouper.sentinel.server;
+
+
+import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
+import io.github.itzispyder.pdk.utils.SchedulerUtils;
+import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
+import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.data.Emojis;
+import io.github.thetrouper.sentinel.server.util.FileUtils;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import io.github.thetrouper.sentinel.server.util.Text;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.GameMode;
+import org.bukkit.Material;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.block.Block;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+public class NewAction {
+
+ private NewAction(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block, boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) {
+ }
+
+ public static class Builder {
+ Cancellable event;
+ ActionType action;
+ private Player player;
+ private String command;
+ private String loggedCommand;
+ private ItemStack item;
+ private Block block;
+ private boolean denied;
+ private boolean deoped;
+ private boolean punished;
+ private boolean revertGM;
+ private boolean notifyDiscord;
+ private boolean notifyTrusted;
+ private boolean notifyConsole;
+ public Builder setEvent(Cancellable event) {
+ this.event = event;
+ return this;
+ }
+ public Builder setAction(ActionType action) {
+ this.action = action;
+ return this;
+ }
+ public Builder setPlayer(Player player) {
+ this.player = player;
+ return this;
+ }
+ public Builder setCommand(String command) {
+ this.command = command;
+ return this;
+ }
+ public Builder setLoggedCommand(String loggedCommand) {
+ this.loggedCommand = loggedCommand;
+ return this;
+ }
+ public Builder setItem(ItemStack item) {
+ this.item = item;
+ return this;
+ }
+ public Builder setBlock(Block block){
+ this.block = block;
+ return this;
+ }
+ public Builder setDenied(boolean denied) {
+ this.denied = denied;
+ return this;
+ }
+ public Builder setDeoped(boolean deoped) {
+ this.deoped = deoped;
+ return this;
+ }
+ public Builder setPunished(boolean punished) {
+ this.punished = punished;
+ return this;
+ }
+ public Builder setRevertGM(boolean revertGM) {
+ this.revertGM = revertGM;
+ return this;
+ }
+ public Builder setNotifyDiscord(boolean notifyDiscord) {
+ this.notifyDiscord= notifyDiscord;
+ return this;
+ }
+ public Builder setNotifyTrusted(boolean notifyTrusted) {
+ this.notifyTrusted = notifyTrusted;
+ return this;
+ }
+ public Builder setNotifyConsole(boolean notifyConsole) {
+ this.notifyConsole = notifyConsole;
+ return this;
+ }
+ public NewAction execute() {
+
+
+ return new NewAction(event, action, player, command, loggedCommand, item, block, denied, deoped, punished, revertGM, notifyDiscord, notifyTrusted, notifyConsole);
+ }
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java
new file mode 100644
index 0000000..12dd2ca
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java
@@ -0,0 +1,102 @@
+package io.github.thetrouper.sentinel.server.functions;
+
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.Emojis;
+import io.github.thetrouper.sentinel.data.FilterActionType;
+import io.github.thetrouper.sentinel.data.FilterSeverity;
+import io.github.thetrouper.sentinel.data.Report;
+import io.github.thetrouper.sentinel.server.FilterAction;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import io.github.thetrouper.sentinel.server.util.Text;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AdvancedBlockers {
+
+ public static void handleAdvanced(AsyncPlayerChatEvent e, Report report) {
+ //if (Sentinel.isTrusted(e.getPlayer())) return;
+ if (Sentinel.mainConfig.chat.useAntiUnicode) handleAntiUnicode(e,report);
+ if (Sentinel.mainConfig.chat.useAntiURL) handleAntiURL(e,report);
+ if (Sentinel.mainConfig.chat.useStrictRegex) handleStrictRegex(e,report);
+ if (Sentinel.mainConfig.chat.useSwearRegex) handleSwearRegex(e,report);
+ }
+
+ public static void handleAntiUnicode(AsyncPlayerChatEvent e, Report report) {
+ if (e.isCancelled()) return;
+ String message = Text.removeFirstColor(e.getMessage());
+ report.stepsTaken().put("Anti-Unicode", "`%s`".formatted(message));
+ ServerUtils.sendDebugMessage("AdvBlocker: Checking for unicode: " + message);
+ String nonAllowed = message.replaceAll(Sentinel.advConfig.allowedCharRegex, "").trim();
+
+ if (nonAllowed.length() != 0) {
+ ServerUtils.sendDebugMessage("AdvBlocker: Caught Unicode: " + nonAllowed);
+ e.setCancelled(true);
+ report.stepsTaken().replace("Anti-Unicode", "`%s` %s".formatted(message, Emojis.alarm));
+ //FilterAction.filterPunish(e,FAT.BLOCK_UNICODE,null,null,report.id());
+ FilterAction.takeAction(e, FilterActionType.UNICODE_BLOCK,report,0,null);
+ }
+ }
+
+ public static void handleSwearRegex(AsyncPlayerChatEvent e, Report report) {
+ if (e.isCancelled()) return;
+ String swearRegex = Sentinel.advConfig.swearRegex;
+
+ Pattern pattern = Pattern.compile(swearRegex, Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(e.getMessage());
+
+ report.stepsTaken().put("Anti-Swear Regex", "`%s`".formatted(e.getMessage()));
+
+ if (matcher.find()) {
+ e.setCancelled(true);
+ String highlighted = Text.regexHighlighter(swearRegex,e.getMessage()," > "," < ");
+ report.stepsTaken().replace("Anti-Swear Regex", "`%s` %s".formatted(highlighted, Emojis.alarm));
+ //FilterAction.filterPunish(e,FAT.SWEAR_PUNISH,null,FilterSeverity.HIGH,report.id());
+ FilterAction.takeAction(e,FilterActionType.SWEAR_PUNISH,report,0,FilterSeverity.MEDIUM);
+ }
+ }
+
+ public static void handleStrictRegex(AsyncPlayerChatEvent e, Report report) {
+ if (e.isCancelled()) return;
+ String strictRegex = Sentinel.advConfig.strictRegex;
+
+ Pattern pattern = Pattern.compile(strictRegex, Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(e.getMessage());
+
+ report.stepsTaken().put("Strict Regex", "`%s`".formatted(e.getMessage()));
+
+
+
+ if (matcher.find()) {
+ e.setCancelled(true);
+ String highlighted = Text.regexHighlighter(strictRegex,e.getMessage()," > "," < ");
+ report.stepsTaken().replace("Strict Regex", "`%s` %s".formatted(highlighted, Emojis.alarm));
+ //FilterAction.filterPunish(e, FAT.SLUR_PUNISH,null, FilterSeverity.SLUR,report.id());
+ FilterAction.takeAction(e,FilterActionType.SLUR_PUNISH,report,0,FilterSeverity.HIGH);
+ }
+ }
+
+ public static void handleAntiURL(AsyncPlayerChatEvent e, Report report) {
+ if (e.isCancelled()) return;
+ String urlRegex = Sentinel.advConfig.urlRegex;
+
+ Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(e.getMessage());
+ //ServerUtils.sendDebugMessage("AdvBlocker: Checking for URLs against regex `%1$s`:%2$s".formatted(urlRegex, e.getMessage()));
+
+ report.stepsTaken().put("Anti-URL", "`%s`".formatted(
+ e.getMessage()
+ ));
+
+ if (matcher.find()) {
+ e.setCancelled(true);
+ String highlighted = Text.regexHighlighter(e.getMessage(),Sentinel.advConfig.urlRegex," > "," < ");
+ ServerUtils.sendDebugMessage("AdvBlocker: Caught URL: " + highlighted);
+ report.stepsTaken().replace("Anti-URL", "`%s` %s".formatted(highlighted, Emojis.alarm));
+
+ //FilterAction.filterPunish(e,FAT.BLOCK_URL,null,null,report.id());
+ FilterAction.takeAction(e,FilterActionType.URL_BLOCK,report,0,null);
+ }
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java
index dc25594..b7b990b 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java
@@ -1,8 +1,10 @@
package io.github.thetrouper.sentinel.server.functions;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.FAT;
-import io.github.thetrouper.sentinel.data.FilterAction;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.Emojis;
+import io.github.thetrouper.sentinel.data.FilterActionType;
+import io.github.thetrouper.sentinel.data.Report;
+import io.github.thetrouper.sentinel.server.FilterAction;
import io.github.thetrouper.sentinel.server.util.GPTUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
@@ -11,102 +13,62 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashMap;
import java.util.Map;
+import java.util.UUID;
public class AntiSpam {
- public static Map heatMap;
- public static Map lastMessageMap;
+ public static Map heatMap = new HashMap<>();
+ public static Map lastMessageMap = new HashMap<>();
- public static void enableAntiSpam() {
- heatMap = new HashMap<>();
- lastMessageMap = new HashMap<>();
- }
-
- public static void handleAntiSpam(AsyncPlayerChatEvent e) {
+ public static void handleAntiSpam(AsyncPlayerChatEvent e, Report report) {
Player p = e.getPlayer();
String message = Text.removeFirstColor(e.getMessage());
+ String lastMessage = lastMessageMap.getOrDefault(p.getUniqueId(),"/* Placeholder Message from Sentinel */");
+ int currentHeat = heatMap.getOrDefault(p.getUniqueId(),0);
+ double similarity = GPTUtils.calcSim(message, lastMessage);
- if (!lastMessageMap.containsKey(p)) {
- lastMessageMap.put(p,"/* Placeholder Message from Sentinel */");
- ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a previous message, setting to placeholder!");
- }
- if (!heatMap.containsKey(p)) {
- heatMap.put(p,0);
- ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a heat, setting it to 0!");
+ int addHeat = Sentinel.mainConfig.chat.antiSpam.defaultGain;
+
+ ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " has a heat of " + currentHeat + "/" + Sentinel.mainConfig.chat.antiSpam.punishHeat + ". Current Message: \"" + message + "\" Last message: \"" + lastMessage + "\"");
+ if (similarity > 90) {
+ addHeat = Sentinel.mainConfig.chat.antiSpam.highGain;
+ ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 90% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.highGain);
+ } else if (similarity > 50) {
+ addHeat = Sentinel.mainConfig.chat.antiSpam.mediumGain;
+ ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 50% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.mediumGain);
+ } else if (similarity > 25) {
+ addHeat = Sentinel.mainConfig.chat.antiSpam.lowGain;
+ ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 25% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.lowGain);
}
- if (lastMessageMap.containsKey(p)) {
- String lastMessage = lastMessageMap.get(p);
- double similarity = GPTUtils.calcSim(message, lastMessage);
- ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " has a heat of " + heatMap.get(p) + "/" + Config.punishHeat + ". Current Message: \"" + message + "\" Last message: \"" + lastMessage + "\"");
- if (similarity > 90) {
- heatMap.put(p, heatMap.get(p) + Config.highGain);
- ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 90% for " + p.getName() + ". Adding " + Config.highGain);
- } else if (similarity > 50) {
- heatMap.put(p, heatMap.get(p) + Config.mediumGain);
- ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 50% for " + p.getName() + ". Adding " + Config.mediumGain);
- } else if (similarity > 25) {
- heatMap.put(p, heatMap.get(p) + Config.lowGain);
- ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 25% for " + p.getName() + ". Adding " + Config.lowGain);
- }
- }
+ report.stepsTaken().put("Anti-Spam", "Heat: %s\nMessage: `%s`".formatted(currentHeat,message));
- if (heatMap.get(p) > Config.punishHeat) {
+ if (currentHeat > Sentinel.mainConfig.chat.antiSpam.punishHeat) {
e.setCancelled(true);
- FilterAction.filterAction(p,e,null,null, GPTUtils.calcSim(e.getMessage(),lastMessageMap.get(p)), FAT.SPAM);
+ report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(currentHeat,message, Emojis.alarm));
+ //FilterAction.filterPunish(e,FAT.SPAM_PUNISH,GPTUtils.calcSim(e.getMessage(),lastMessage), null,report.id());
+ FilterAction.takeAction(e, FilterActionType.SPAM_PUNISH,report,similarity,null);
return;
}
- if (heatMap.get(p) > Config.blockHeat) {
+ if (currentHeat > Sentinel.mainConfig.chat.antiSpam.blockHeat) {
e.setCancelled(true);
- FilterAction.filterAction(p,e,null,null, GPTUtils.calcSim(e.getMessage(),lastMessageMap.get(p)), FAT.BLOCK_SPAM);
- heatMap.put(p, heatMap.get(p) + Config.highGain);
+ report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(currentHeat,message, Emojis.alarm));
+ //FilterAction.filterPunish(e,FAT.BLOCK_SPAM, GPTUtils.calcSim(e.getMessage(),lastMessage), null,report.id());
+ FilterAction.takeAction(e,FilterActionType.SPAM_BLOCK,report,similarity,null);
+ heatMap.put(p.getUniqueId(), currentHeat + Sentinel.mainConfig.chat.antiSpam.highGain);
return;
}
- lastMessageMap.put(p, message);
+
+ heatMap.put(p.getUniqueId(),currentHeat + addHeat);
}
public static void decayHeat() {
- for (Player p : heatMap.keySet()) {
- int heat = heatMap.get(p);
+ for (UUID p : heatMap.keySet()) {
+ int heat = heatMap.getOrDefault(p,0);
if (heat > 0) {
- heat = heat - Config.heatDecay;
+ heat = heat - Sentinel.mainConfig.chat.antiSpam.heatDecay;
heatMap.put(p, Math.max(0, heat));
}
//ServerUtils.sendDebugMessage("AntiSpam: Decaying heat for " + p.getName() + ": " + heatMap.get(p));
}
}
- /*
- public static void alertSpam(Player p, String message1, String message2) {
- TextComponent text = new TextComponent();
- double similarity = GPTUtils.calculateSimilarity(message1,message2 + "%");
- DecimalFormat fs = new DecimalFormat("##.#");
- fs.setRoundingMode(RoundingMode.DOWN);
- TextComponent warning = new TextComponent();
- warning.setText(Text.prefix(Sentinel.dict.get("spam-warning")));
- warning.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("action-automatic")));
- p.spigot().sendMessage(warning);
- text.setText(Text.prefix(Sentinel.dict.get("spam-notification").formatted(p.getName(),heatMap.get(p),Config.punishHeat)));
- text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("spam-notification-hover").formatted(message1,message2,fs.format(similarity)))));
- ServerUtils.forEachStaff(staff -> {
- staff.spigot().sendMessage(text);
- });
- }
- public static void punishSpam(Player p, String message1, String message2) {
- boolean chatCleared = false;
- if (Config.clearChat) {
- ServerUtils.sendCommand(Config.chatClearCommand);
- chatCleared = true;
- }
- ServerUtils.sendCommand(Config.spamPunishCommand.replace("%player%", p.getName()));
- TextComponent warning = new TextComponent();
- warning.setText(Text.prefix(Sentinel.dict.get("spam-punished")));
- warning.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("action-automatic"))));
- p.spigot().sendMessage(warning);
- TextComponent text = new TextComponent();
- text.setText(Text.prefix(Sentinel.dict.get("spam-punish-notification").formatted(p.getName(),heatMap.get(p),Config.punishHeat)));
- ServerUtils.forEachStaff(staff -> {
- staff.spigot().sendMessage(text);
- });
- if (Config.logSpam) WebhookSender.sendSpamLog(p,message1,message2,heatMap.get(p),chatCleared);
- }
- */
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiUnicode.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiUnicode.java
deleted file mode 100644
index ea32160..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiUnicode.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.github.thetrouper.sentinel.server.functions;
-
-import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.event.player.AsyncPlayerChatEvent;
-
-public class AntiUnicode {
- public static void handleAntiUnicode(AsyncPlayerChatEvent e) {
- String message = Text.removeFirstColor(e.getMessage());
- String nonAllowed = message.replaceAll("[A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_]", "").trim();
- if (message.matches("https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)")) {
-
- }
- if (nonAllowed.length() != 0) {
- e.getPlayer().sendMessage(Text.prefix(Sentinel.dict.get("unicode-warn")));
- e.setCancelled(true);
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java
index 8f760df..d5c2d15 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java
@@ -1,124 +1,101 @@
package io.github.thetrouper.sentinel.server.functions;
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import io.github.thetrouper.sentinel.server.util.MathUtils;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.net.InetAddress;
+import java.net.HttpURLConnection;
import java.net.URL;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
public class Authenticator {
- public Authenticator() throws UnknownHostException {
- }
- private static final String ENCRYPTION_KEY = "lllIIlllIlSentinelAuthIllIllllII";
- private static final String ENCRYPTION_ALGORITHM = "AES";
- private static final String ENCRYPTION_MODE_PADDING = "AES/ECB/PKCS5Padding";
- static InetAddress IP;
-
- static {
- try {
- IP = InetAddress.getLocalHost();
- } catch (UnknownHostException e) {
- throw new RuntimeException(e);
- }
- }
-
public static String authorize(String licenseKey, String serverID) {
- String authStatus = "";
+ Map> licenses = getLicenseList();
- try {
- URL url = new URL("https://trouper.me/auth/sentinel");
- BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
- List lines = readLines(reader);
-
- for (String line : lines) {
- if (line.contains("data-key")) {
- String key = extractValue(line, "data-key");
- String allowedIDs = extractValue(line, "data-allowed");
- String[] allowedArr = allowedIDs.split(":");
-
- if (key.equals(licenseKey)) {
- if (Arrays.asList(allowedArr).contains(serverID)) {
- authStatus = "AUTHOReIZED";
- return authStatus;
- } else {
- if (Arrays.asList(allowedArr).contains("minehut")) {
- authStatus = "MINEHUT";
- return authStatus;
- }
- authStatus = "INVALID-ID";
- return authStatus;
- }
- }
- }
+ if (licenses.containsKey(licenseKey)) {
+ List allowedIDs = licenses.get(licenseKey);
+ if (allowedIDs.contains(serverID)) {
+ return "AUTHORIZED";
+ } else if (allowedIDs.contains("minehut")) {
+ return "MINEHUT";
+ } else {
+ return "INVALID-ID";
}
-
- if (authStatus.isEmpty()) {
- authStatus = "UNREGISTERED";
- return authStatus;
- }
- } catch (IOException e) {
- e.printStackTrace();
}
- return authStatus;
+ return "UNREGISTERED";
}
- public static List readLines(BufferedReader reader) {
- try {
- List lines = new ArrayList<>();
- String line = reader.readLine();
- while (line != null) {
- lines.add(line);
- line = reader.readLine();
- }
- reader.close();
- return lines;
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- return new ArrayList<>();
- }
-
- public static String extractValue(String line, String attribute) {
- int start = line.indexOf(attribute + "=\"") + attribute.length() + 2;
- int end = line.indexOf("\"", start);
- return line.substring(start, end);
- }
-
-
-
public static String getServerID() {
- return encrypt(IP.getHostAddress());
- }
-
-
- public static String encrypt(String text) {
try {
- SecretKeySpec secretKey = new SecretKeySpec(ENCRYPTION_KEY.getBytes(), ENCRYPTION_ALGORITHM);
- Cipher cipher = Cipher.getInstance(ENCRYPTION_MODE_PADDING);
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
-
- byte[] encryptedBytes = cipher.doFinal(text.getBytes());
- String encryptedText = bytesToHex(encryptedBytes);
- return encryptedText;
+ return MathUtils.SHA512(getPublicIPAddress());
} catch (Exception e) {
- e.printStackTrace();
+ return "NULL";
}
- return "ERR";
}
- private 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 Map> getLicenseList() {
+ try {
+ String urlString = "http://api.trouper.me:8080/sentinel";
+ URL url = new URL(urlString);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+
+ int responseCode = conn.getResponseCode();
+ if (responseCode != HttpURLConnection.HTTP_OK) {
+ throw new IOException("Failed to get response from server, response code: " + responseCode);
+ }
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ String inputLine;
+ StringBuilder content = new StringBuilder();
+ while ((inputLine = in.readLine()) != null) {
+ content.append(inputLine);
+ }
+ in.close();
+ conn.disconnect();
+
+ Gson gson = new Gson();
+
+ return gson.fromJson(content.toString(), new TypeToken>>() {}.getType());
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ public static String getPublicIPAddress() throws IOException {
+ String apiUrl = "http://checkip.amazonaws.com";
+
+ URL url = new URL(apiUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ try {
+ connection.setRequestMethod("GET");
+
+ int responseCode = connection.getResponseCode();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ String line;
+ StringBuilder response = new StringBuilder();
+
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
+ }
+
+ reader.close();
+
+ return response.toString().trim();
+ } else {
+ throw new IOException("Failed to get public IP address. HTTP error code: " + responseCode);
+ }
+ } finally {
+ connection.disconnect();
}
- return result.toString();
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/CMDBlockWhitelist.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/CMDBlockWhitelist.java
new file mode 100644
index 0000000..e4c2461
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/CMDBlockWhitelist.java
@@ -0,0 +1,181 @@
+package io.github.thetrouper.sentinel.server.functions;
+
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import io.github.thetrouper.sentinel.server.util.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.persistence.PersistentDataType;
+
+import java.util.UUID;
+
+public class CMDBlockWhitelist {
+
+ public static void add(CommandBlock cb, UUID owner) {
+ ServerUtils.sendDebugMessage("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;
+ if (!Sentinel.isTrusted(cb.owner())) return false;
+ return true;
+ }
+ 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.sendDebugMessage("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.sendDebugMessage("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.sendDebugMessage("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
+ );
+ }
+
+
+ private static boolean getNBTBoolean(CommandBlock cmdBlock, String key) {
+ return cmdBlock.getPersistentDataContainer().has(
+ getKey(key),
+ PersistentDataType.BYTE
+ ) && cmdBlock.getPersistentDataContainer().get(
+ getKey(key),
+ PersistentDataType.BYTE
+ ) == 1;
+ }
+
+ private static NamespacedKey getKey(String key) {
+ return new NamespacedKey(Sentinel.getInstance(), key);
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Load.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Load.java
new file mode 100644
index 0000000..0855ba5
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Load.java
@@ -0,0 +1,133 @@
+package io.github.thetrouper.sentinel.server.functions;
+
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.auth.Auth;
+import io.github.thetrouper.sentinel.cmds.*;
+import io.github.thetrouper.sentinel.events.*;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
+import org.bukkit.Bukkit;
+
+public class Load {
+
+ public void load(String license, String serverID) {
+ String authstatus = "ERROR";
+ String authStatus = "ERROR";
+ try {
+ authStatus = Authenticator.authorize(license, serverID);
+ authstatus = Auth.authorize(license, serverID);
+ Sentinel.IP = Authenticator.getPublicIPAddress();
+ Sentinel.log.info("Auth Requested...");
+ } catch (Exception e) {
+ e.printStackTrace();
+ Sentinel.log.info("WTFFFF ARE YOU DOING MAN??????");
+ liteStart();
+ }
+ switch (authStatus) {
+ case "AUTHORIZED" -> {
+ Sentinel.log.info("\n]======----- Auth Success! -----======[");
+ startup();
+ }
+ case "MINEHUT" -> {
+ Sentinel.usesDynamicIP = true;
+ Telemetry.initTelemetryHook();
+ boolean minehutStatus = Telemetry.sendStartupLog();
+ if (minehutStatus) {
+ authstatus = authstatus.replaceAll("ur a skid lmao", "get out of here kiddo");
+ ServerUtils.sendDebugMessage(authstatus);
+ Sentinel.log.info("Dynamic IP auth Success! ");
+ this.startup();
+ } else {
+ Sentinel. log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this.");
+ liteStart();
+ }
+ }
+ case "INVALID-ID" -> {
+ Sentinel.log.info("Authentication Failure, You have not whitelisted this server ID yet.");
+ liteStart();
+ }
+ case "UNREGISTERED" -> {
+ Sentinel.log.warning("Authentication Failure, YOU SHALL NOT PASS! License: %s Server ID: %s".formatted(license,serverID));
+ liteStart();
+ }
+ case "ERROR" -> {
+ Sentinel.log.warning("Hmmmmmm thats not right... License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,serverID));
+ liteStart();
+ }
+ default -> {
+ Sentinel.log.warning("Achievement unlocked: How did we get here? License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,serverID));
+ liteStart();
+ }
+ }
+ }
+
+ public static boolean lite = false;
+
+ public void liteStart() {
+ lite = true;
+
+ Telemetry.initTelemetryHook();
+ if (!Telemetry.sendLiteLog()) {
+ Sentinel.manager.disablePlugin(Sentinel.getInstance());
+ return;
+ }
+
+ new SentinelCommand().register();
+
+ Sentinel.log.info("""
+ Finished!
+ ____ __ ___ \s
+ /\\ _`\\ /\\ \\__ __ /\\_ \\ \s
+ \\ \\,\\L\\_\\ __ ___\\ \\ ,_\\/\\_\\ ___ __\\//\\ \\ \s
+ \\/_\\__ \\ /'__`\\/' _ `\\ \\ \\/\\/\\ \\ /' _ `\\ /'__`\\\\ \\ \\ \s
+ /\\ \\L\\ \\/\\ __//\\ \\/\\ \\ \\ \\_\\ \\ \\/\\ \\/\\ \\/\\ __/ \\_\\ \\_\s
+ \\ `\\____\\ \\____\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\_\\ \\____\\/\\____\\
+ \\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/
+ ]==-- Enabled Lite mode. Go verify your purchase. --==[
+ """);
+ }
+
+ public void startup() {
+ Sentinel.log.info("\n]======----- Loading Sentinel! -----======[");
+
+ // Plugin startup logic
+ Sentinel.log.info("Starting Up! (%s)...".formatted(Sentinel.getInstance().getDescription().getVersion()));
+
+ // Commands
+ new SentinelCommand().register();
+ new MessageCommand().register();
+ new ReplyCommand().register();
+ new ReopCommand().register();
+ new SocialSpyCommand().register();
+ new ChatClickCallback().register();
+
+ // Events
+ new ChatEvent().register();
+ new CommandEvent().register();
+ new CMDBlockExecute().register();
+ new CMDBlockPlace().register();
+ new CMDBlockUse().register();
+ new CMDMinecartPlace().register();
+ new CMDMinecartUse().register();
+ new NBTEvents().register();
+ new MiscEvents().register();
+ if (Sentinel.doNoPlugins) {
+ new TrapCommand().register();
+ new PluginHiderEvents().register();
+ TabCompleteEvent.registerEvent(Sentinel.getInstance());
+ }
+
+ // Scheduled timers
+ Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), AntiSpam::decayHeat,0, 20);
+ Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), ProfanityFilter::decayScore,0,1200);
+ Sentinel.log.info("""
+ Finished!
+ ____ __ ___ \s
+ /\\ _`\\ /\\ \\__ __ /\\_ \\ \s
+ \\ \\,\\L\\_\\ __ ___\\ \\ ,_\\/\\_\\ ___ __\\//\\ \\ \s
+ \\/_\\__ \\ /'__`\\/' _ `\\ \\ \\/\\/\\ \\ /' _ `\\ /'__`\\\\ \\ \\ \s
+ /\\ \\L\\ \\/\\ __//\\ \\/\\ \\ \\ \\_\\ \\ \\/\\ \\/\\ \\/\\ __/ \\_\\ \\_\s
+ \\ `\\____\\ \\____\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\_\\ \\____\\/\\____\\
+ \\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/
+ ]====---- Advanced Anti-Grief & Chat Filter ----====[""");
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java
index d255bda..3a008e9 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java
@@ -1,47 +1,44 @@
package io.github.thetrouper.sentinel.server.functions;
+import io.github.itzispyder.pdk.utils.ServerUtils;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.commands.MessageCommand;
-import io.github.thetrouper.sentinel.commands.SocialSpyCommand;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import net.md_5.bungee.api.chat.HoverEvent;
-import net.md_5.bungee.api.chat.TextComponent;
-import net.md_5.bungee.api.chat.hover.content.Text;
+import io.github.thetrouper.sentinel.cmds.SocialSpyCommand;
+import io.github.thetrouper.sentinel.events.ChatEvent;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextComponent;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
public class Message {
- private static final Map replyMap = MessageCommand.replyMap;
+ public static final Map replyMap = new HashMap<>();
public static void messagePlayer(Player sender, Player receiver, String message) {
HashSet receivers = new HashSet<>();
receivers.add(receiver);
receivers.add(sender);
AsyncPlayerChatEvent checkEvent = new AsyncPlayerChatEvent(true,sender,message,receivers);
if (checkEvent.isCancelled()) return;
- if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antiswear.bypass")) if (Config.antiSwearEnabled) ProfanityFilter.handleProfanityFilter(checkEvent);
- if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antispam.bypass")) if (Config.antiSpamEnabled) AntiSpam.handleAntiSpam(checkEvent);
- if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antiunicode.bypass")) if (Config.antiUnicode) AntiUnicode.handleAntiUnicode(checkEvent);
- if (checkEvent.isCancelled()) {
- return;
- }
+ ChatEvent.handleChatEvent(checkEvent);
+ if (checkEvent.isCancelled()) return;
- sender.sendMessage(Sentinel.dict.get("message-sent").formatted(receiver.getName(),message));
- receiver.sendMessage(Sentinel.dict.get("message-received").formatted(sender.getName(),message));
+ sender.sendMessage(Sentinel.lang.playerInteraction.messageSent.formatted(receiver.getName(),message));
+ receiver.sendMessage(Sentinel.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) {
ServerUtils.forEachPlayer(player -> {
+
if (SocialSpyCommand.spyMap.getOrDefault(player.getUniqueId(),false)) {
- TextComponent notification = new TextComponent(Sentinel.dict.get("spy-message").formatted(sender.getName(),receiver.getName()));
- notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Sentinel.dict.get("spy-message-hover").formatted(sender.getName(),receiver.getName(),message))));
- player.spigot().sendMessage(notification);
+ 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)));
+ player.sendMessage(notification);
}
});
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java
index 597252c..2b0422c 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java
@@ -1,169 +1,75 @@
package io.github.thetrouper.sentinel.server.functions;
-import io.github.thetrouper.sentinel.data.Config;
-import io.github.thetrouper.sentinel.data.FilterAction;
-import io.github.thetrouper.sentinel.data.FAT;
+
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.data.*;
+import io.github.thetrouper.sentinel.server.FilterAction;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
-import java.util.List;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-
-import static io.github.thetrouper.sentinel.server.util.Text.SECTION_SYMBOL;
+import java.util.UUID;
public class ProfanityFilter {
- public static Map scoreMap;
- private static final List swearBlacklist = Config.swearBlacklist;
- private static final List swearWhitelist = Config.swearWhitelist;
- private static final List slurs = Config.slurs;
+ public static Map scoreMap = new HashMap<>();
+ private static final List swearBlacklist = Sentinel.swearConfig.swears;
+ private static final List swearWhitelist = Sentinel.fpConfig.swearWhitelist;
+ private static final List slurs = Sentinel.strictConfig.strict;
- public static void enableAntiSwear() {
- scoreMap = new HashMap<>();
- }
- public static void handleProfanityFilter(AsyncPlayerChatEvent e) {
- Player p = e.getPlayer();
- String message = Text.removeFirstColor(e.getMessage());
- String highlighted = highlightProfanity(message);
- String severity = ProfanityFilter.checkSeverity(message);
- if (!scoreMap.containsKey(p)) scoreMap.put(p, 0);
- // Old: if (scoreMap.get(p) > Config.punishScore) punishSwear(p,highlighted,message,e);
- if (scoreMap.get(p) > Config.punishScore) FilterAction.filterAction(p,e,highlighted,severity, null, FAT.SWEAR);
+ public static void handleProfanityFilter(AsyncPlayerChatEvent event, Report report) {
+ Player player = event.getPlayer();
+ String message = Text.removeFirstColor(event.getMessage());
+ FilterSeverity severity = checkSeverity(message,report);
- switch (severity) {
- case "low" -> {
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.lowScore);
- scoreMap.put(p, scoreMap.get(p) + Config.lowScore);
- e.setCancelled(true);
- // Old: blockSwear(p,highlighted,message,severity,e);
- FilterAction.filterAction(p,e,highlighted,severity, null, FAT.BLOCK_SWEAR);
- }
- case "medium-low" -> {
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.mediumLowScore);
- scoreMap.put(p, scoreMap.get(p) + Config.mediumLowScore);
- e.setCancelled(true);
- // Old: blockSwear(p,highlighted,message,severity,e);
- FilterAction.filterAction(p,e,highlighted,severity, null, FAT.BLOCK_SWEAR);
- }
- case "medium" -> {
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.mediumScore);
- scoreMap.put(p, scoreMap.get(p) + Config.mediumScore);
- e.setCancelled(true);
- // Old: blockSwear(p,highlighted,message,severity,e);
- FilterAction.filterAction(p,e,highlighted,severity, null, FAT.BLOCK_SWEAR);
- }
- case "medium-high" -> {
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.mediumHighScore);
- scoreMap.put(p, scoreMap.get(p) + Config.mediumHighScore);
- e.setCancelled(true);
- // Old: blockSwear(p,highlighted,message,severity,e);
- FilterAction.filterAction(p,e,highlighted,severity, null, FAT.BLOCK_SWEAR);
- }
- case "high" -> {
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.highScore);
- scoreMap.put(p, scoreMap.get(p) + Config.highScore);
- e.setCancelled(true);
- // Old: blockSwear(p,highlighted,message,severity,e);
- FilterAction.filterAction(p,e,highlighted,severity, null, FAT.BLOCK_SWEAR);
- }
- case "slur" -> {
- // Insta-Punish
- ServerUtils.sendDebugMessage("AntiSwear Flag, Message: " + message + " Concentrated: " + fullSimplify(message) + " Severity: " + severity + " Previous Score: " + scoreMap.get(p) +" Adding Score: " + Config.highScore);
- scoreMap.put(p, scoreMap.get(p) + Config.highScore);
- e.setCancelled(true);
- // Old: punishSlur(p,highlighted,message,e);
- FilterAction.filterAction(p,e,highlighted,severity, null,FAT.SLUR);
- }
+ if (severity.equals(FilterSeverity.SAFE)) return;
+
+ scoreMap.putIfAbsent(player.getUniqueId(), 0);
+ int previousScore = scoreMap.get(player.getUniqueId());
+ ServerUtils.sendDebugMessage(String.format("AntiSwear Flag, Message: %s Concentrated: %s Severity: %s Previous Score: %d Adding Score: %d",
+ message, fullSimplify(message), severity, previousScore, severity.getScore()));
+ event.setCancelled(true);
+
+ int newScore = previousScore + severity.getScore();
+ scoreMap.put(player.getUniqueId(), newScore);
+
+ if (newScore > Sentinel.mainConfig.chat.antiSwear.punishScore) {
+ FilterAction.takeAction(event,FilterActionType.SWEAR_PUNISH,report,0,severity);
+ return;
}
+ FilterAction.takeAction(event,getFilterActionType(severity),report,0,severity);
+ //FilterAction.filterPunish(event, getFAT(severity), null, severity,report.id());
}
- /*
- public static void punishSwear(Player player, String highlightedMSG, String origMessage, AsyncPlayerChatEvent e) {
- ServerUtils.sendCommand(Config.swearPunishCommand.replace("%player%", player.getName()));
- String fpreport = ReportFalsePositives.generateReport(e);
- TextComponent offender = new TextComponent();
- String hoverPlayer = Sentinel.dict.get("action-automatic-reportable");
- offender.setText(Text.prefix(Sentinel.dict.get("profanity-mute-warn")));
- offender.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hoverPlayer)));
- offender.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + fpreport));
- player.spigot().sendMessage(offender);
-
- TextComponent text = new TextComponent();
- text.setText(Text.prefix(Sentinel.dict.get("profanity-mute-notification").formatted(player.getName(),scoreMap.get(player),Config.punishScore)));
- text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("filter-notification-hover").formatted(origMessage,highlightedMSG))));
- text.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + fpreport));
-
- ServerUtils.forEachStaff(staff -> {
- staff.spigot().sendMessage(text);
- });
- if (Config.logSwear) WebhookSender.sendSwearLog(player,origMessage,scoreMap.get(player));
+ public static FilterActionType getFilterActionType(FilterSeverity severity) {
+ return switch (severity) {
+ case SLUR -> FilterActionType.SLUR_PUNISH;
+ case LOW,MEDIUM_LOW,MEDIUM,MEDIUM_HIGH,HIGH -> FilterActionType.SWEAR_BLOCK;
+ case SAFE -> FilterActionType.SAFE;
+ };
}
-
- public static void punishSlur(Player player, String highlightedMSG, String origMessage, AsyncPlayerChatEvent e) {
- if (!Config.strictInstaPunish) return;
-
- ServerUtils.sendCommand(Config.strictPunishCommand.replace("%player%", player.getName()));
- String fpreport = ReportFalsePositives.generateReport(e);
- TextComponent offender = new TextComponent();
- String hoverPlayer = Sentinel.dict.get("action-automatic-reportable");
- offender.setText(Text.prefix((Sentinel.dict.get("slur-mute-warn"))));
- offender.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hoverPlayer)));
- offender.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + fpreport));
- player.spigot().sendMessage(offender);
- TextComponent text = new TextComponent();
- text.setText(Text.prefix(Sentinel.dict.get("slur-mute-notification").formatted(player.getName(),scoreMap.get(player),Config.punishScore)));
- text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("filter-notification-hover").formatted(origMessage,highlightedMSG))));
- text.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + fpreport));
-
- ServerUtils.forEachStaff(staff -> {
- staff.spigot().sendMessage(text);
- });
- if (Config.logSwear) WebhookSender.sendSlurLog(player,origMessage,scoreMap.get(player));
- }
- public static void blockSwear(Player player, String highlightedMSG, String origMessage, String severity, AsyncPlayerChatEvent e) {
- String FPReport = ReportFalsePositives.generateReport(e);
- TextComponent offender = new TextComponent();
- String hover = Sentinel.dict.get("action-automatic-reportable");
- offender.setText(Text.prefix((Sentinel.dict.get("swear-block-warn"))));
- offender.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hover)));
- offender.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + FPReport));
- player.spigot().sendMessage(offender);
-
- TextComponent staff = new TextComponent();
- staff.setText(Text.prefix(Sentinel.dict.get("swear-block-notification").formatted(player.getName(),scoreMap.get(player),Config.punishScore)));
- staff.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.dict.get("severity-notification-hover").formatted(origMessage,highlightedMSG,severity))));
- staff.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + FPReport));
-
- ServerUtils.forEachStaff(staffmember -> {
- staffmember.spigot().sendMessage(staff);
- });
- }
-*/
public static String highlightProfanity(String text) {
- String highlightedSwears = highlightSwears(fullSimplify(text), "&e", "&f");
- String highlightedText = highlightSlurs(highlightedSwears, "&c", "&f");
- return Text.color(highlightedText);
+ return highlightProfanity(text, "&e", "&f");
}
+
public static String highlightProfanity(String text, String start, String end) {
String highlightedSwears = highlightSwears(fullSimplify(text), start, end);
- String highlightedText = highlightSlurs(highlightedSwears, start, end);
- return Text.color(highlightedText);
+ return Text.color(highlightSlurs(highlightedSwears, start, end));
}
private static String highlightSwears(String text, String start, String end) {
for (String swear : swearBlacklist) {
- if (text.contains(swear)) {text = text.replace(swear, start + swear + end);}
+ text = text.replace(swear, start + swear + end);
}
return text;
}
private static String highlightSlurs(String text, String start, String end) {
for (String slur : slurs) {
- if (text.contains(slur)) {
- text = text.replace(slur, start + slur + end);
- }
+ text = text.replace(slur, start + slur + end);
}
return text;
}
@@ -190,60 +96,90 @@ public class ProfanityFilter {
String convertedText = convertLeetSpeakCharacters(cleanedText);
String strippedText = stripSpecialCharacters(convertedText);
String simplifiedText = simplifyRepeatingLetters(strippedText);
- String finalText = removePeriodsAndSpaces(simplifiedText);
- return finalText;
+ return removePeriodsAndSpaces(simplifiedText);
}
- public static String checkSeverity(String text) {
+ public static FilterSeverity checkSeverity(String text, Report report) {
+ FilterSeverity severity = FilterSeverity.SAFE;
// 1:
String lowercasedText = text.toLowerCase();
+ report.stepsTaken().put("Lowercased", lowercasedText);
ServerUtils.sendDebugMessage("ProfanityFilter: Lowercased: " + lowercasedText);
// 2:
String cleanedText = removeFalsePositives(lowercasedText);
+ report.stepsTaken().put("Remove False Positives", cleanedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Removed False positives: " + cleanedText));
// 3:
- if (containsSwears(cleanedText)) return "low";
- if (containsSlurs(cleanedText)) return "slur";
+ severity = checkProfanity(cleanedText,FilterSeverity.LOW);
+ if (severity != FilterSeverity.SAFE) {
+ report.stepsTaken().replace("Remove False Positives", "%s %s".formatted(
+ highlightProfanity(cleanedText,"||","||"),
+ Emojis.alarm));
+ return severity;
+ }
// 4:
String convertedText = convertLeetSpeakCharacters(cleanedText);
+ report.stepsTaken().put("Convert LeetSpeak", convertedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Leet Converted: " + convertedText));
// 5:
- if (containsSwears(convertedText)) return "medium-low";
- if (containsSlurs(cleanedText)) return "slur";
-
+ severity = checkProfanity(convertedText,FilterSeverity.MEDIUM_LOW);
+ if (severity != FilterSeverity.SAFE) {
+ report.stepsTaken().replace("Convert LeetSpeak", "%s %s".formatted(
+ highlightProfanity(cleanedText,"||","||"),
+ Emojis.alarm));
+ return severity;
+ }
// 6:
String strippedText = stripSpecialCharacters(convertedText);
+ report.stepsTaken().put("Remove Special Characters", strippedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Specials Removed: " + strippedText));
// 7:
- if (containsSwears(strippedText)) return "medium";
- if (containsSlurs(strippedText)) return "slur";
-
+ severity = checkProfanity(strippedText,FilterSeverity.MEDIUM);
+ if (severity != FilterSeverity.SAFE) {
+ report.stepsTaken().replace("Remove Special Characters", "%s %s".formatted(
+ highlightProfanity(cleanedText,"||","||"),
+ Emojis.alarm));
+ return severity;
+ }
// 8:
String simplifiedText = simplifyRepeatingLetters(strippedText);
+ report.stepsTaken().put("Remove Repeats", simplifiedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Removed Repeating: " + simplifiedText));
// 9:
- if (containsSwears(simplifiedText)) return "medium-high";
- if (containsSlurs(simplifiedText)) return "slur";
-
+ severity = checkProfanity(simplifiedText,FilterSeverity.MEDIUM_HIGH);
+ if (severity != FilterSeverity.SAFE) {
+ report.stepsTaken().replace("Remove Repeats", "%s %s".formatted(
+ highlightProfanity(cleanedText,"||","||"),
+ Emojis.alarm));
+ return severity;
+ }
// 10:
String finalText = removePeriodsAndSpaces(simplifiedText);
+ report.stepsTaken().put("Remove Punctuation", finalText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Remove Punctuation: " + finalText));
// 11:
- if (containsSwears(finalText)) return "high";
- if (containsSlurs(finalText)) return "slur";
+ severity = checkProfanity(finalText,FilterSeverity.HIGH);
+ if (severity != FilterSeverity.SAFE) {
+ report.stepsTaken().replace("Remove Punctuation", "%s %s".formatted(
+ highlightProfanity(cleanedText,"||","||"),
+ Emojis.alarm));
+ return severity;
+ }
- return "safe";
+ return severity;
}
- public static boolean ContainsProfanity(String text) {
- return containsSwears(text) || containsSlurs(text);
+ public static FilterSeverity checkProfanity(String text, FilterSeverity severity) {
+ if (containsSlurs(text)) return FilterSeverity.SLUR;
+ if (containsSwears(text)) return severity;
+ return FilterSeverity.SAFE;
}
private static boolean containsSwears(String text) {
ServerUtils.sendDebugMessage("ProfanityFilter: Checking for swears");
@@ -263,6 +199,7 @@ public class ProfanityFilter {
for (String falsePositive : swearWhitelist) {
text = text.replace(falsePositive, "");
}
+ text = text.replaceAll(Sentinel.advConfig.falsePosRegex,"");
return text;
}
public static String convertLeetSpeakCharacters(String text) {
@@ -284,11 +221,11 @@ public class ProfanityFilter {
return text.replaceAll("[^A-Za-z0-9]", "").replace(" ", "");
}
public static void decayScore() {
- for (Player p : scoreMap.keySet()) {
- int score = scoreMap.get(p);
+ for (UUID uuid : scoreMap.keySet()) {
+ int score = scoreMap.get(uuid);
if (score > 0) {
- score = score - Config.scoreDecay;
- scoreMap.put(p, Math.max(0, score));
+ score = score - Sentinel.mainConfig.chat.antiSwear.scoreDecay;
+ scoreMap.put(uuid, Math.max(0, score));
}
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java
index d9b9166..5bf9856 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java
@@ -1,85 +1,58 @@
package io.github.thetrouper.sentinel.server.functions;
+import io.github.itzispyder.pdk.utils.SchedulerUtils;
+import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
+import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
import io.github.thetrouper.sentinel.data.Emojis;
-import io.github.thetrouper.sentinel.discord.DiscordWebhook;
+import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.util.Randomizer;
-import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import io.github.thetrouper.sentinel.server.util.Text;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
-import java.awt.*;
-import java.io.IOException;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
public class ReportFalsePositives {
- public static Map reportMap = new HashMap<>();
- public static String generateReport(AsyncPlayerChatEvent e) {
- final long reportLong = Randomizer.generateID();
- final String reportID = Long.toString(reportLong);
- ServerUtils.sendDebugMessage("FP Report: Generating chat filter report");
- reportMap.put(reportID,e);
- ServerUtils.sendDebugMessage(("FP Report: Generated chat filter report. ID:" + reportID + " Message: \"" + reportMap.get(reportID).getMessage() + "\" Expires in 60 seconds"));
- Bukkit.getScheduler().runTaskLater(Sentinel.getInstance(),()->{
- reportMap.remove(reportID);
- ServerUtils.sendDebugMessage("FP Report: Chat filter Report expired. ID: " + reportID);
- },60000);
- return reportID;
- }
- public static void sendFalsePositiveReport(String reportID) {
- AsyncPlayerChatEvent e = reportMap.get(reportID);
- String orig = e.getMessage();
-
- String lowercasedText = orig.toLowerCase();
- String remFP = ProfanityFilter.removeFalsePositives(lowercasedText);
- String convertedLeet = ProfanityFilter.convertLeetSpeakCharacters(remFP);
- String remSpecials = ProfanityFilter.stripSpecialCharacters(convertedLeet);
- String simplifyRep = ProfanityFilter.simplifyRepeatingLetters(remSpecials);
- String sanitized = ProfanityFilter. removePeriodsAndSpaces(simplifyRep);
-
- sendEmbed(e.getPlayer(),orig,lowercasedText,remFP,convertedLeet,remSpecials,simplifyRep,sanitized);
+ public static Map reports = new HashMap<>();
+ public static Report initializeReport(AsyncPlayerChatEvent event) {
+ final long reportID = Randomizer.generateID();
+ LinkedHashMap steps = new LinkedHashMap<>();
+ steps.put("Original Message", "`%s`".formatted(event.getMessage()));
+ SchedulerUtils.later(1200,()->{
+ reports.remove(reportID);
+ });
+ return new Report(reportID,event,steps);
}
- public static void sendEmbed(Player player,
- String message,
- String lowercased,
- String remFP,
- String convertedLeet,
- String remSpecials,
- String simplifyRep,
- String sanitized) {
- ServerUtils.sendDebugMessage("Creating FalsePositive Webhook...");
- DiscordWebhook webhook = new DiscordWebhook(Config.webhook);
- webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png");
- webhook.setUsername("Sentinel Anti-Nuke | Logs");
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor("Anti-Swear False Positive","","")
- .setTitle("Flag Report:")
- .setDescription(
- Emojis.rightSort + "Player: " + player.getName() + " " + Emojis.target + "\\n" +
- Emojis.space + Emojis.arrowRight + "UUID: `" + player.getUniqueId() + "`\\n"
- )
- .addField("Original Message", "`" + message + "` " + (ProfanityFilter.ContainsProfanity(message) ? Emojis.alarm : ""), false)
- .addField("Lowercase", "`" + lowercased + "` " + (ProfanityFilter.ContainsProfanity(lowercased) ? Emojis.alarm : ""), false)
- .addField("Removed FPs", "`" + remFP + "` " + (ProfanityFilter.ContainsProfanity(remFP) ? Emojis.alarm : ""), false)
- .addField("Converted Leet", "`" + convertedLeet + "` " + (ProfanityFilter.ContainsProfanity(convertedLeet) ? Emojis.alarm : ""), false)
- .addField("Removed Specials", "`" + remSpecials + "` " + (ProfanityFilter.ContainsProfanity(remSpecials) ? Emojis.alarm : ""), false)
- .addField("Simplify Repeats", "`" + simplifyRep + "` " + (ProfanityFilter.ContainsProfanity(simplifyRep) ? Emojis.alarm : ""), false)
- .addField("Fully Sanitized Message", ProfanityFilter.highlightProfanity(sanitized,"`", "`") + " " + Emojis.noDM, false)
- .setColor(Color.green)
- .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId() + "?size=64&&overlay");
- webhook.addEmbed(embed);
- try {
- ServerUtils.sendDebugMessage("FP Report: Executing webhook...");
- webhook.execute();
- } catch (IOException e) {
- ServerUtils.sendDebugMessage("FP Report: Epic webhook failure!!!");
- Sentinel.log.info(e.toString());
- }
+ public static void sendFalsePositiveReport(Report report) {
+ DiscordEmbed.Builder embed = DiscordEmbed.create()
+ .author(new DiscordEmbed.Author("Anti-Swear False Positive","",null))
+ .title("A player has reported a false positive")
+ .desc(String.format("""
+ %1$sPlayer: %2$s %3$s
+ %4$s %5$sUUID: `%6$s`
+ ## **Filter Steps Taken:**
+ """,
+ Emojis.rightSort,
+ report.event().getPlayer().getName(),
+ Emojis.target,
+ Emojis.space,
+ Emojis.rightArrow,
+ report.event().getPlayer().getUniqueId()
+ ));
+
+ report.stepsTaken().forEach((key, value)->{
+ embed.addField(new DiscordEmbed.Field(key,value));
+ });
+
+ DiscordWebhook.create()
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .username("Sentinel Anti-Nuke | Logs")
+ .addEmbed(embed.build())
+ .send(Sentinel.mainConfig.plugin.webhook);
+
+ reports.remove(report.id());
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java
new file mode 100644
index 0000000..c5e2626
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java
@@ -0,0 +1,165 @@
+package io.github.thetrouper.sentinel.server.functions;
+
+import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
+import io.github.itzispyder.pdk.utils.SchedulerUtils;
+import io.github.thetrouper.sentinel.Sentinel;
+import io.github.thetrouper.sentinel.cmds.SocialSpyCommand;
+import io.github.thetrouper.sentinel.data.ActionType;
+import io.github.thetrouper.sentinel.events.CommandEvent;
+import io.github.thetrouper.sentinel.server.Action;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.attribute.AttributeModifier;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.BlockState;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.inventory.InventoryCreativeEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.PlayerCommandPreprocessEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+import java.util.Set;
+
+public class SystemCheck {
+
+ private static Material save = Material.AIR;
+
+ public static void fullCheck(Player p) {
+ if (!Sentinel.isTrusted(p)) return;
+ Sentinel.mainConfig.plugin.trustedPlayers.remove(p.getUniqueId().toString());
+
+ chatCheck(p);
+ p.setOp(true);
+ cmdPlaceCheck(p);
+ p.setOp(true);
+ cmdBlockUseCheck(p);
+ p.setOp(true);
+ commandCheck(p);
+ p.setOp(true);
+ nbtCheck(p);
+ p.setOp(true);
+ cleanup(p);
+
+ Sentinel.mainConfig.plugin.trustedPlayers.add(p.getUniqueId().toString());
+
+ }
+
+ public static void cleanup(Player p) {
+ Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
+ placed.setType(save);
+ }
+
+ public static void cmdPlaceCheck(Player p) {
+ Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
+ save = placed.getType();
+ BlockState bs = placed.getState();
+ placed.setType(Material.COMMAND_BLOCK);
+ EquipmentSlot es = EquipmentSlot.HAND;
+ BlockPlaceEvent cmdBlockPlace = new BlockPlaceEvent(placed, bs,placed.getLocation().clone().add(0,-1,0).getBlock(),new ItemBuilder().material(Material.COMMAND_BLOCK).build(),p,true,es);
+ Action a = new Action.Builder()
+ .setAction(ActionType.UPDATE_COMMAND_BLOCK)
+ .setEvent(cmdBlockPlace)
+ .setBlock(placed)
+ .setCommand("Sentinel CMDBlockPlace Check")
+ .setPlayer(p)
+ .setDenied(true)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
+ p.setOp(true);
+ }
+
+ public static void cmdBlockUseCheck(Player p) {
+ Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
+ Material before = placed.getType();
+ placed.setType(Material.COMMAND_BLOCK);
+ PlayerInteractEvent cmdUse = new PlayerInteractEvent(p, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK,ItemBuilder.create().material(Material.AIR).build(),placed, BlockFace.UP);
+ Action a = new Action.Builder()
+ .setAction(ActionType.USE_COMMAND_BLOCK)
+ .setEvent(cmdUse)
+ .setBlock(placed)
+ .setPlayer(p)
+ .setDenied(true)
+ .setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
+ .setNotifyTrusted(true)
+ .setNotifyConsole(true)
+ .execute();
+ p.setOp(true);
+ placed.setType(before);
+ }
+
+ public static void commandCheck(Player p) {
+ PlayerCommandPreprocessEvent command = new PlayerCommandPreprocessEvent(p,"fill ~ ~ ~ ~ ~ ~ air");
+ PlayerCommandPreprocessEvent command2 = new PlayerCommandPreprocessEvent(p,"give @s illegal_item 1");
+ PlayerCommandPreprocessEvent command3 = new PlayerCommandPreprocessEvent(p,"bukkit:plugins");
+ new CommandEvent().onCommand(command);
+ p.setOp(true);
+ new CommandEvent().onCommand(command2);
+ p.setOp(true);
+ new CommandEvent().onCommand(command3);
+ p.setOp(true);
+ }
+
+ public static void nbtCheck(Player p) {
+ ItemStack i = ItemBuilder.create()
+ .material(Material.STICK)
+ .name("Name")
+ .lore(List.of("lore"))
+ .enchant(Enchantment.DAMAGE_ALL,255)
+ .attribute(Attribute.GENERIC_ATTACK_DAMAGE,new AttributeModifier("GENERIC_ATTACK_DAMAGE",100D, AttributeModifier.Operation.ADD_NUMBER))
+ .build();
+ InventoryCreativeEvent nbt = new InventoryCreativeEvent(p.openInventory(p.getInventory()), InventoryType.SlotType.QUICKBAR,8, i);
+ nbt.setCursor(i);
+ Action a = new Action.Builder()
+ .setEvent(nbt)
+ .setAction(ActionType.NBT)
+ .setPlayer(Bukkit.getPlayer(nbt.getWhoClicked().getName()))
+ .setItem(nbt.getCursor())
+ .setDenied(Sentinel.mainConfig.plugin.preventNBT)
+ .setDeoped(Sentinel.mainConfig.plugin.deop)
+ .setPunished(Sentinel.mainConfig.plugin.nbtPunish)
+ .setRevertGM(Sentinel.mainConfig.plugin.preventNBT)
+ .setNotifyConsole(true)
+ .setNotifyTrusted(true)
+ .setNotifyDiscord(Sentinel.mainConfig.plugin.logNBT)
+ .execute();
+ p.setOp(true);
+ }
+
+
+ public static void chatCheck(Player p) {
+ SocialSpyCommand.spyMap.put(p.getUniqueId(),true);
+
+ AsyncPlayerChatEvent swear = new AsyncPlayerChatEvent(true,p,"Sentinel AntiSwear check > Fvck", Set.of(p));
+ AsyncPlayerChatEvent spam = new AsyncPlayerChatEvent(true,p,"Sentinel AntiSpam check", Set.of(p));
+ AsyncPlayerChatEvent falsePositive = new AsyncPlayerChatEvent(true,p,"Sentinel False Positive check > I like sentanal anti nuke", Set.of(p));
+ AsyncPlayerChatEvent unicode = new AsyncPlayerChatEvent(true,p,"\u202Elmao i am bypassing the filter tihs ", Set.of(p));
+ AsyncPlayerChatEvent url = new AsyncPlayerChatEvent(true,p,"join my lifesteal server! play.cringsteal.net", Set.of(p));
+ ProfanityFilter.handleProfanityFilter(swear,ReportFalsePositives.initializeReport(swear));
+ AdvancedBlockers.handleAntiUnicode(unicode,ReportFalsePositives.initializeReport(unicode));
+ AdvancedBlockers.handleAntiURL(url,ReportFalsePositives.initializeReport(url));
+ SchedulerUtils.loop(5,4, (loop)->{
+ AntiSpam.lastMessageMap.put(p.getUniqueId(),"Sentinel AntiSpam Check");
+ AntiSpam.handleAntiSpam(spam,ReportFalsePositives.initializeReport(spam));
+ });
+
+ SchedulerUtils.later(20,()->{
+
+ });
+
+ Message.messagePlayer(p,p,"Sentinel Automatic System check > Private Message");
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java
index 9cb5ee2..80f537b 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java
@@ -1,145 +1,141 @@
package io.github.thetrouper.sentinel.server.functions;
+import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
+import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.discord.DiscordWebhook;
+import io.github.thetrouper.sentinel.data.Emojis;
+import io.github.thetrouper.sentinel.server.util.CipherUtils;
+import io.github.thetrouper.sentinel.server.util.ServerUtils;
-import java.awt.*;
import java.io.BufferedReader;
-import java.io.IOException;
import java.io.InputStreamReader;
-import java.net.InetAddress;
+import java.net.HttpURLConnection;
import java.net.URL;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class Telemetry {
-
- public Telemetry() throws UnknownHostException {
- }
- static InetAddress IP;
-
- static {
- try {
- IP = InetAddress.getLocalHost();
- } catch (UnknownHostException e) {
- throw new RuntimeException(e);
- }
+ public static String webhook;
+ public static void initTelemetryHook() {
+ webhook = fetchTelemetryHook();
}
- public static String telemetryHook;
-
- public static String loadTelemetryHook(String serverID, String licenseKey) {
- String hook = "";
+ public static boolean sendStartupLog() {
try {
- URL url = new URL("https://sentinelauth.000webhostapp.com/telemetrykey.html");
- BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
- List lines = readLines(reader);
-
- for (String line : lines) {
- if (line.contains("data-id")) {
- hook = extractValue(line, "data-hook");
- telemetryHook = hook;
- Map response = sendStartupLog(serverID,licenseKey);
-
- if (response.containsKey("SUCCESS")) {
- Sentinel.log.info("Successfully grabbed telemetry hook");
- return "SUCCESS";
- } else {
- Sentinel.log.info("An Error occurred while attempting to connect to the telemetry hook: " + response.get("ERROR"));
- return "FAIL";
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return "ERROR";
- }
-
- public static Map testWebhook(String hook) {
- Map response = new HashMap<>();
- response.put("SUCCESS", "NULL");
- DiscordWebhook webhook = new DiscordWebhook(hook);
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor("Test Success!", "", "")
- .setDescription("Connected to webhook")
- .setColor(Color.GREEN);
- webhook.addEmbed(embed);
- try {
- webhook.execute();
- } catch (IOException e) {
- response.clear();
- response.put("ERROR", e.toString());
- return response;
- }
- return response;
- }
-
- public static List readLines(BufferedReader reader) {
- try {
- List lines = new ArrayList<>();
- String line = reader.readLine();
- while (line != null) {
- lines.add(line);
- line = reader.readLine();
- }
- reader.close();
- return lines;
+ DiscordWebhook.create()
+ .username("Sentinel Anti-Nuke | Telemetry")
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .addEmbed(DiscordEmbed.create()
+ .author(new DiscordEmbed.Author("Server Startup Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
+ .title("A server has started up successfully")
+ .desc("Server " + Sentinel.serverID + "\n" +
+ Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
+ Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
+ .color(0x44FF44)
+ .build()
+ ).send(webhook);
+ return true;
} catch (Exception ex) {
+ Sentinel.log.info("Failed to initialize dynamic auth!");
+ return false;
+ }
+ }
+
+ public static boolean sendLiteLog() {
+ try {
+ DiscordWebhook.create()
+ .username("Sentinel Anti-Nuke | Telemetry")
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .addEmbed(DiscordEmbed.create()
+ .author(new DiscordEmbed.Author("Server Startup Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
+ .title("A server has started up in lite mode")
+ .desc("Server " + Sentinel.serverID + "\n" +
+ Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
+ Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
+ .color(0x440044)
+ .build()
+ ).send(webhook);
+ return true;
+ } catch (Exception ex) {
+ Sentinel.log.info("Failed to initialize lite mode!");
+ return false;
+ }
+ }
+
+ public static void sendShutdownLog() {
+ try {
+ DiscordWebhook.create()
+ .username("Sentinel Anti-Nuke | Telemetry")
+ .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
+ .addEmbed(DiscordEmbed.create()
+ .author(new DiscordEmbed.Author("Server Shutdown Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
+ .title("A server has shut down")
+ .desc("Server " + Sentinel.serverID + "\n" +
+ Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
+ Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
+ .color(0xFF0000)
+ .build()
+ ).send(webhook);
+ } catch (Exception ex) {
+ Sentinel.log.info("Failed to send dynamic shutdown!");
+ }
+ }
+
+ public static String fetchTelemetryHook() {
+ try {
+ final String webhook = extractWebhook(fetchHtmlContent("https://trouper.me/auth/telemetry"));
+ ServerUtils.sendDebugMessage("Original Webhook: " + webhook);
+
+ String webhookIdPart = webhook.replaceAll(".*/(\\d+)/([^/]+.*)$", "/$1/");
+ ServerUtils.sendDebugMessage("Webhook ID Part: " + webhookIdPart);
+
+ String encrypted = webhook.replaceAll(".*/\\d+/([^/]+.*)$", "$1");
+ ServerUtils.sendDebugMessage("Encrypted Part: " + encrypted);
+
+ String isolated = webhook.replaceAll("/\\d+/([^/]+.*)$", "");
+ ServerUtils.sendDebugMessage("Isolated Part: " + isolated);
+
+ String decrypted = isolated + webhookIdPart + CipherUtils.decrypt(encrypted);
+ ServerUtils.sendDebugMessage("Decrypted Result: " + decrypted);
+
+ return decrypted;
+ } catch (Exception ex) {
+ Sentinel.log.warning("FAILED TO LOAD TELEMETRY (Are the servers up?)");
ex.printStackTrace();
+ return "NULL";
}
- return new ArrayList<>();
}
- public static String extractValue(String line, String attribute) {
- int start = line.indexOf(attribute + "=\"") + attribute.length() + 2;
- int end = line.indexOf("\"", start);
- return line.substring(start, end);
- }
+ private static String fetchHtmlContent(String urlString) throws Exception {
+ URL url = new URL(urlString);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
- public static Map sendStartupLog(String serverID, String licenseKey) {
- Map response = new HashMap<>();
- response.put("SUCCESS", "NULL");
- DiscordWebhook webhook = new DiscordWebhook(telemetryHook);
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor("Server Startup Log", "", "")
- .setTitle("Dynamic IP server connected")
- .setDescription("License key: `"+ licenseKey + "`\\n" +
- "Server ID: `" + serverID + "`")
- .setColor(Color.GREEN);
- webhook.addEmbed(embed);
- try {
- webhook.execute();
- } catch (IOException e) {
- response.clear();
- response.put("ERROR", e.toString());
- return response;
+ BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ StringBuilder response = new StringBuilder();
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
}
- return response;
+ reader.close();
+ connection.disconnect();
+
+ return response.toString();
}
- public static Map sendShutdownLog(String serverID, String licenseKey) {
- Map response = new HashMap<>();
- response.put("SUCCESS", "NULL");
- DiscordWebhook webhook = new DiscordWebhook(telemetryHook);
- DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
- .setAuthor("Server Shutdown Log", "", "")
- .setTitle("Dynamic IP server disconnected")
- .setDescription("License key: `"+ licenseKey + "`\\n" +
- "Server ID: `" + serverID + "`")
- .setColor(Color.RED);
- webhook.addEmbed(embed);
- try {
- webhook.execute();
- } catch (IOException e) {
- response.clear();
- response.put("ERROR", e.toString());
- return response;
+
+ private static String extractWebhook(String htmlContent) {
+ String pattern = "data-hook=\"(.*?)\"";
+ Pattern r = Pattern.compile(pattern);
+ Matcher m = r.matcher(htmlContent);
+
+ if (m.find()) {
+ return m.group(1);
+ } else {
+ return "Webhook ID not found";
}
- return response;
-
}
+
+
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java
deleted file mode 100644
index 5415385..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :)
- */
-
-package io.github.thetrouper.sentinel.server.util;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Represents Argument builder
- */
-public class ArgBuilder {
-
- private String result;
-
- /**
- * Constructs an argument builder.
- */
- public ArgBuilder() {
- this.result = " ";
- }
-
- /**
- * Constructs an argument builder with a string.
- * @param begin the beginner string
- */
- public ArgBuilder(String begin) {
- this.result = begin + " ";
- }
-
- /**
- * Appends a string
- * @param string string
- * @return this class
- */
- public ArgBuilder append(String string) {
- this.result += string + " ";
- return this;
- }
-
- /**
- * Appends a string array
- * @param args string array
- * @return this class
- */
- public ArgBuilder append(String[] args) {
- StringBuilder builder = new StringBuilder();
- for (String arg : args) builder.append(arg).append(" ");
- this.result += builder.toString();
- return this;
- }
-
- /**
- * Appends a string list
- * @param args string list
- * @return this class
- */
- public ArgBuilder append(List args) {
- StringBuilder builder = new StringBuilder();
- for (String arg : args) builder.append(arg).append(" ");
- this.result += builder.toString();
- return this;
- }
-
- /**
- * Appends a string set
- * @param args string set
- * @return this class
- */
- public ArgBuilder append(Set args) {
- StringBuilder builder = new StringBuilder();
- for (String arg : args) builder.append(arg).append(" ");
- this.result += builder.toString();
- return this;
- }
-
- /**
- * Returns this class as a string
- * @return this class as a string
- */
- public String build() {
- return this.toString().trim();
- }
-
- @Override
- public String toString() {
- return result;
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java
deleted file mode 100644
index 3a8fbec..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.github.thetrouper.sentinel.server.util;
-
-import org.bukkit.Material;
-import org.bukkit.entity.EntityType;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Function;
-
-public final class ArrayUtils {
-
- /**
- * Transforms an array to another one
- * @param e iterable list
- * @param a action
- * @return new transformed list
- * @param input
- * @param output
- */
- public static List toNewList(Iterable e, Function a) {
- List list = new ArrayList<>();
- e.forEach(i -> list.add(a.apply(i)));
- return list;
- }
-
- public static String list2string(List list) {
- return ("\u00a77[\u00a7e" + String.join("\u00a77, \u00a7e", ArrayUtils.toNewList(list, Object::toString)) + "\u00a77]");
- }
-
- public static List bind(Iterable tList, T... ts) {
- List list = Arrays.asList(ts);
- tList.forEach(list::add);
- return list;
- }
-
- public static class Constants {
- public static final List MATERIAL_NAMES = toNewList(Arrays.stream(Material.values()).toList(),m -> m.name().toLowerCase());
- public static final List ENTITY_NAMES = toNewList(Arrays.stream(EntityType.values()).toList(),e -> e.name().toLowerCase());
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java
new file mode 100644
index 0000000..83f52b4
--- /dev/null
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java
@@ -0,0 +1,35 @@
+package io.github.thetrouper.sentinel.server.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+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;
+ }
+}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java
deleted file mode 100644
index f772a05..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.github.thetrouper.sentinel.server.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class Cooldown {
-
- private final Map timer;
-
- public Cooldown() {
- this.timer = new HashMap<>();
- }
-
- private O getOrDefault(O value, O def) {
- return value != null ? value : def;
- }
-
- public long getCooldown(T obj) {
- return Math.max(getOrDefault(timer.get(obj), 0L) - System.currentTimeMillis(), 0L);
- }
-
- public double getCooldownSec(T obj) {
- final long cooldown = this.getCooldown(obj);
- return MathUtils.round(cooldown / 1000.0, 100);
- }
-
- public boolean isOnCooldown(T obj) {
- return getCooldown(obj) > 0L;
- }
-
- public void setCooldown(T obj, long millis) {
- timer.put(obj, System.currentTimeMillis() + millis);
- }
-
- public void addCooldown(T obj, long millis) {
- setCooldown(obj, getCooldown(obj) + millis);
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java
index 92c7f60..05276ca 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java
@@ -1,33 +1,13 @@
package io.github.thetrouper.sentinel.server.util;
-import com.google.gson.reflect.TypeToken;
+import io.github.itzispyder.pdk.utils.FileValidationUtils;
import io.github.thetrouper.sentinel.Sentinel;
+import org.bukkit.inventory.ItemStack;
-import java.io.*;
-import java.time.*;
-import java.util.List;
-import java.util.Random;
-import com.google.gson.Gson;
-import org.bukkit.Location;
-import com.google.gson.Gson;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.Map;
+import java.io.BufferedWriter;
+import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.util.Map;
-import java.util.UUID;
-import com.google.gson.Gson;
-import java.lang.reflect.Type;
-import java.io.FileWriter;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.Map;
-import java.util.List;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.UUID;
-import org.bukkit.Location;
public class FileUtils {
public static boolean folderExists(String folderName) {
File folder = new File(Sentinel.getInstance().getDataFolder(), folderName);
@@ -66,9 +46,42 @@ public class FileUtils {
return fileName;
}
+ public static String createNBTLog(ItemStack i) {
+ ServerUtils.sendDebugMessage("FileUtils: Creating NBT log");
+
+ String item = i.getType().name().toLowerCase() + i.getItemMeta().getAsString();
+
+ String fileName = "nbt_log-" + Randomizer.generateID();
+
+ File dataFolder = Sentinel.getInstance().getDataFolder();
+
+ File loggedNBTFolder = new File(dataFolder,"LoggedNBT");
+ if (!loggedNBTFolder.exists()) {
+ loggedNBTFolder.mkdirs();
+ }
+
+ File file = new File(loggedNBTFolder, fileName + ".txt");
+ try {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+
+ BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
+ writer.append(item);
+ writer.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return fileName;
+ }
+
+
public static String createCommandLog(String command) {
+
String fileName = "command_log-" + Randomizer.generateID();
File file = new File(Sentinel.getInstance().getDataFolder() + "/LoggedCommands/" + fileName + ".txt");
+ FileValidationUtils.validate(file);
try {
if (!file.exists()) {
file.createNewFile();
@@ -81,6 +94,7 @@ public class FileUtils {
} catch (IOException e) {
e.printStackTrace();
}
+
return fileName;
}
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/FileValidationUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/FileValidationUtils.java
deleted file mode 100644
index d2a0024..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/FileValidationUtils.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.github.thetrouper.sentinel.server.util;
-
-import java.io.File;
-
-public final class FileValidationUtils {
-
- public static boolean validate(File file) {
- try {
- if (!file.getParentFile().exists())
- if (!file.getParentFile().mkdirs())
- return false;
- if (!file.exists())
- return file.createNewFile();
- return true;
- }
- catch (Exception ex) {
- return false;
- }
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/JsonSerializable.java b/src/main/java/io/github/thetrouper/sentinel/server/util/JsonSerializable.java
deleted file mode 100644
index afc36c5..0000000
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/JsonSerializable.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package io.github.thetrouper.sentinel.server.util;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import java.io.*;
-
-public interface JsonSerializable {
-
- Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
- File getFile();
-
- default String serialize(boolean pretty) {
- Gson gson;
- if (pretty) {
- gson = new GsonBuilder().setPrettyPrinting().create();
- }
- else {
- gson = new Gson();
- }
-
- try {
- String json = gson.toJson(this);
- if (json == null) {
- throw new IllegalStateException("json parse failed for " + this.getClass().getSimpleName());
- }
- return json;
- }
- catch (Exception ex) {
- return "{}";
- }
- }
-
- @SuppressWarnings("unchecked")
- default T deserialize(String json) {
- try {
- JsonSerializable> v = gson.fromJson(json, this.getClass());
- if (v == null) {
- throw new IllegalStateException("json parse failed");
- }
- return (T)v;
- }
- catch (Exception ex) {
- return null;
- }
- }
-
- default void save() {
- String json = serialize(true);
- File f = getFile();
-
- if (FileValidationUtils.validate(f)) {
- try {
- FileWriter fw = new FileWriter(f);
- BufferedWriter bw = new BufferedWriter(fw);
- bw.write(json);
- bw.close();
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
-
- default O getOrDef(O val, O def) {
- return val != null ? val : def;
- }
-
- static > T load(File file, Class jsonSerializable, T fallback) {
- if (FileValidationUtils.validate(file)) {
- try {
- FileReader fr = new FileReader(file);
- BufferedReader br = new BufferedReader(fr);
- T t = gson.fromJson(br, jsonSerializable);
-
- if (t == null) {
- throw new IllegalStateException("json parse failed!");
- }
-
- return t;
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- return fallback;
- }
-
- static > T load(String path, Class jsonSerializable, T fallback) {
- return load(new File(path), jsonSerializable, fallback);
- }
-}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/MathUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/MathUtils.java
index e33c4c2..a93ea25 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/MathUtils.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/MathUtils.java
@@ -1,5 +1,8 @@
package io.github.thetrouper.sentinel.server.util;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -20,4 +23,36 @@ public final class MathUtils {
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));
+ }
+ return result.toString();
+ }
+
+ public static String SHA512(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;
+ }
+ }
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java
index 940965f..105ce8a 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java
@@ -1,10 +1,10 @@
package io.github.thetrouper.sentinel.server.util;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Set;
-import java.text.SimpleDateFormat;
-import java.util.Date;
/**
* Randomize items from a list
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java
index 84c2800..98326c5 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java
@@ -1,12 +1,13 @@
package io.github.thetrouper.sentinel.server.util;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.commands.SentinelCommand;
+import io.github.thetrouper.sentinel.cmds.SentinelCommand;
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.entity.Player;
+import org.bukkit.metadata.MetadataValue;
import java.util.ArrayList;
import java.util.Arrays;
@@ -27,7 +28,7 @@ public class ServerUtils {
},1);
}
public static void sendDebugMessage(String message) {
- if (SentinelCommand.debugmode) {
+ if (SentinelCommand.debugMode) {
String log = "[Sentinel] [DEBUG]: " + message;
Sentinel.log.info(log);
for (Player trustedPlayer : Bukkit.getOnlinePlayers()) {
@@ -90,4 +91,15 @@ public class ServerUtils {
}
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);
+ }
}
diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java
index ab15b1f..128bfa1 100644
--- a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java
+++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java
@@ -2,19 +2,42 @@ package io.github.thetrouper.sentinel.server.util;
import io.github.thetrouper.sentinel.Sentinel;
-import io.github.thetrouper.sentinel.data.Config;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class Text {
+
+ public static String regexHighlighter(String input, String regex, String startString, String endString) {
+ // Create a Pattern object
+ Pattern pattern = Pattern.compile(regex);
+
+ // Create a Matcher object
+ Matcher matcher = pattern.matcher(input);
+
+ // StringBuffer to store the result
+ StringBuffer result = new StringBuffer();
+
+ // Find and append matches
+ while (matcher.find()) {
+ matcher.appendReplacement(result, startString + matcher.group() + endString);
+ }
+
+ // Append the remainder of the input
+ matcher.appendTail(result);
+
+ return result.toString();
+ }
+
public static final char SECTION_SYMBOL = (char)167;
public static String color(String msg) {
return msg.replace('&', SECTION_SYMBOL);
}
public static String prefix(String text) {
- String prefix = Sentinel.prefix;
+ String prefix = Sentinel.mainConfig.plugin.prefix;
return color(prefix + text);
}
public static String removeFirstColor(String input) {
@@ -28,27 +51,42 @@ public class Text {
return input;
}
}
- public static String replaceRepeatingLetters(String message) {
- StringBuilder result = new StringBuilder();
- char prevChar = '\0';
- int count = 0;
+ public static String replaceRepeatingLetters(String input) {
+ if (input == null || input.isEmpty()) {
+ return input;
+ }
- for (char c : message.toCharArray()) {
- if (c == prevChar) {
+ StringBuilder simplifiedText = new StringBuilder();
+ char currentChar = input.charAt(0);
+ int count = 1;
+
+ for (int i = 1; i < input.length(); i++) {
+ char nextChar = input.charAt(i);
+
+ if (Character.toLowerCase(nextChar) == Character.toLowerCase(currentChar)) {
count++;
- if (count <= 3) {
- result.append(c);
- }
} else {
- prevChar = c;
+ simplifiedText.append(currentChar);
+
+ if (count > 1) {
+ simplifiedText.append(currentChar);
+ }
+
+ currentChar = nextChar;
count = 1;
- result.append(c);
}
}
- return result.toString();
+
+ simplifiedText.append(currentChar);
+
+ if (count > 1) {
+ simplifiedText.append(currentChar);
+ }
+
+ return simplifiedText.toString();
}
public static String fromLeetString(String s) {
- Map dictionary = Config.leetPatterns;
+ Map dictionary = Sentinel.advConfig.leetPatterns;
String msg = s;
for (String key : dictionary.keySet()) {
@@ -68,4 +106,8 @@ public class Text {
}
return msg;
}
+
+ public static String cleanName(String type) {
+ return type.replaceAll("_"," ").toLowerCase();
+ }
}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
deleted file mode 100644
index 6fe96f9..0000000
--- a/src/main/resources/config.yml
+++ /dev/null
@@ -1,111 +0,0 @@
-# Sentinel 0.2.0
-# ____ __ ___
-#/\ _`\ /\ \__ __ /\_ \
-#\ \,\L\_\ __ ___\ \ ,_\/\_\ ___ __\//\ \
-# \/_\__ \ /'__`\/' _ `\ \ \/\/\ \ /' _ `\ /'__`\\ \ \
-# /\ \L\ \/\ __//\ \/\ \ \ \_\ \ \/\ \/\ \/\ __/ \_\ \_
-# \ `\____\ \____\ \_\ \_\ \__\\ \_\ \_\ \_\ \____\/\____\
-# \/_____/\/____/\/_/\/_/\/__/ \/_/\/_/\/_/\/____/\/____/
-# ]======------ Configuration & Setup Guide ------=====[
-# Sentinel is inspired by WickBot.com
-# Be sure to check out their amazing discord bot!
-# If you need help, join the discord!
-# https://discord.gg/sentinelmc v Use below if it expired
-# https://sentinelauth.000webhostapp.com/discord.html
-#
-config:
- plugin:
- key: "beta" # Put your license key here. If you do not have one, join the discord to verify your purchase
- lang: "en_us.json" # Languages
- # --------------------------------
- # Anti-Nuke Setup (Do this first)
- # --------------------------------
- prefix: "§d§lSentinel §8» §7" # Prefix of the plugin. Line below is the discord webhook for logs to be sent to
- webhook: "https://discord.com/api/webhooks/id/token"
- trusted: # List the UUIDs of players who are trusted, will bypass the plugin and be immune to logs and are able to re-op themeselves, as well as whitelist command blocks
- - "049460f7-21cb-42f5-8059-d42752bf406f" # obvWolf
- block-specific: true # Defaulted true | Weather or not to block ALL plugin specific commands from non-trusted members (EX: minecraft:execute) these will not be logged.
- prevent-nbt: true # Defaulted true | Should NBT items be blocked from the creative hotbar
- prevent-cmdblock-place: true # Defaulted true | Should Placing a command block get blocked
- prevent-cmdblock-use: true # Defaulted true | Should using a command block get blocked
- prevent-cmdblock-change: true # Defaulted true | Should changing a command block get blocked
- prevent-cmdcart-place: true # Defaulted true | Should placing a command cart get blocked
- prevent-cmdcart-use: true # Defaulted true | Should using a command cart get blocked
- cmdblock-op-check: true # Defaulted true | Will check if a player is op'd before preforming actions against command blocks (To prevent spam from non oped users attempting command blocks, which they cant by default)
- dangerous: # These commands can only be run by "trusted" users
- - "op"
- - "deop"
- - "stop"
- - "restart"
- - "execute" # Could run commands as a trusted player
- - "sudo" # same as above
- - "esudo" # WATCH OUT FOR ESSENTIALS ALIASES !!!
- - "fill" # Most client side nukers use it
- - "setblock" # could setblock a command block with anything
- - "data" # Could modify a command block to whatever they wanted
- - "whitelist" # Could add other players to the whitelist
- log-dangerous: true # Default true | Weather or not to log to discord when a dangerous command is executed
- log-cmdblocks: true # Defaulted true | Log attempts of command-block place-ery in discord
- log-nbt: true # Defaulted true | Should items and their NBT's be logged to discord
- log-specific: false # Default false | Weather or not to log to discord when a plugin specific command is executed
- logged: # Commands that will always be logged to discord when executed.
- - "give"
- - "item"
- deop: true # Defaulted true | This will remove an untrusted player's operator permissions whenever they attempt dangerous actions
- nbt-punish: false # Defaulted false | This will punish a player when they attempt to use an NBT item
- cmdblock-punish: false # Defaulted false | This will punish a player when they attempt to use a command block
- command-punish: false # Defaulted false | This will ban punish player when they attempt to use a dangerous command
- specific-punish: false # Defaulted false | This will punish a player when they run a specific command (Not recomended)
- punish-commands: # Commands to run when a dangerous action is to be punished. Use %player% for the punished player's name
- - "smite %player%"
- - "ban %player% ]=- Sentinel -=[ You have been banned for attempting a dangerous action. If you believe this to be a mistake, please contact the server owner."
- reop-command: false # Defaulted false | This enables the command allowing trusted players to op themselves if they get deoped.
- # -------------------------------
- # Chat Filter Setup & AntiSpam
- # -------------------------------
- chat:
- anti-unicode: true # Default true | Prevents all non A-Z 0-9 + specials from being sent in chat
- anti-spam:
- # AntiSpam Heat system
- enabled: true # Default true | Enables/disables the entire anti-spam
- default-gain: 1 # Default 1 | Heat gained as base for every message
- low-gain: 2 # Default 2 | Heat gained when message is >25% similar
- medium-gain: 4 # Default 4 | Heat gained when message is >50% similar
- high-gain: 6 # Default 6 | Heat gained for >90% similarity
- heat-decay: 1 # Default 1 | Heat lost every second
- block-heat: 10 # Default 10 | The heat required to block the message
- punish-heat: 25 # Default 25 | The heat required to punish the player
- clear-chat: true # Default true | will run the clear chat command before a spam punishment
- chat-clear-command: "cc" # Default cc | Command for if "clear-chat" is enabled
- punish-command: "mute %player% 1m Please refrain from spamming!" # (Use %player% for the player's name placeholder)
- log-spam: true # Default true | logs spam punishments to the webhook
- anti-swear:
- enabled: true # Default true | Enables/disables the entire anti-swear
- low-score: 0 # Default 0 | How much score should you gain for not attempting a bypass
- medium-low-score: 1 # Default 1 | How much score should you gain for "bad "bypass attempt
- medium-score: 3 # Default 3 | How much score should you gain for "ok" bypass attempt
- medium-high-score: 5 # Default 5 | How much score should you gain for "good" bypass attempt
- high-score: 7 # Default 7 | How much score should be gained for "extreme" attempt to bypass
- score-decay: 3 # Default 3 | Rate at which score is lost every minute
- punish-score: 20 # Default 20 | how much score is required to get punished
- strict-insta-punish: true # Default true | Should players get insta punished for any words on the "strict" list?
- punish-command: "mute %player% 15m Do not attempt to bypass the Profanity Filter"
- strict-command: "mute %player% 1h Discriminatory speech is not tolerated on this server!"
- log-swear: true # Default true | Logs swear punishments to the webhook
- leet-patterns: # Replacement patterns for "l33t" strings
- '0': o
- '1': i
- '3': e
- '4': a
- '5': s
- '6': g
- '7': l
- $: s
- '!': i
- '|': i
- +: t
- '#': h
- '@': a
- <: c
- V: u
- v: u
\ No newline at end of file
diff --git a/src/main/resources/false-positives.yml b/src/main/resources/false-positives.yml
deleted file mode 100644
index dae5905..0000000
--- a/src/main/resources/false-positives.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-false-positives: # Words that will falsly flag the anti-swear
- - but then
- - was scamming
- - an alt
- - can also
- - analysis
- - analytics
- - arsenal
- - assassin
- - as saying
- - assert
- - assign
- - assimil
- - assist
- - associat
- - assum
- - assur
- - basement
- - bass
- - cass
- - butter
- - canvass
- - cocktail
- - cumber
- - document
- - evaluate
- - exclusive
- - expensive
- - explain
- - expression
- - grape
- - grass
- - harass
- - hotwater
- - identit
- - kassa
- - kassi
- - lass
- - leafage
- - libshitz
- - magnacumlaude
- - mass
- - mocha
- - pass
- - phoebe
- - phoenix
- - push it
- - sassy
- - saturday
- - scrap
- - serfage
- - sexist
- - shoe
- - stitch
- - therapist
\ No newline at end of file
diff --git a/src/main/resources/lang/en_us.json b/src/main/resources/lang/en_us.json
deleted file mode 100644
index 6407ed2..0000000
--- a/src/main/resources/lang/en_us.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "dictionary" : {
- "example-message" : "Test Message",
- "no-permission" : "§cInsufficient Permissions!",
- "cooldown" : "This action is on cooldown!",
- "false-positive-report-success" : "Successfully reported a false positive!",
- "no-online-player" : "§cYou must provide an online player to send a message to!",
- "no-message-provided" : "§cYou must provide a message to send!",
- "elevating-perms" : "Elevating your permissions...",
- "log-elevating-perms" : "Elevating the permissions of %s",
- "already-op" : "You are already a server operator!",
- "log-already-op" : "The permissions of %s are already elevated! Retrying...",
- "no-trust" : "You are not a trusted user!",
- "no-user-reply" : "§cYou have nobody to reply to!",
- "spy-enabled" : "SocialSpy is now enabled.",
- "spy-disabled" : "SocialSpy is now disabled.",
- "action-automatic" : "§7This action was preformed automatically\n§7by the §bSentinel Anti-Spam§7 algorithm.",
- "action-automatic-reportable" : "§7This action was preformed automatically \n§7by the §bSentinel Profanity Filter§7 algorithm!\n§8§o(Click to report false positive)",
- "unicode-warn" : "§cDo not send non standard unicode in chat!",
- "message-sent" : "§d§lMessage §8» §b[§fYou §e>§f %1$s§b] §7%2$s",
- "message-received" : "§d§lMessage §8» §b[§f%1$s §e>§f You§b] §7%2$s",
- "spy-message" : "§d§lSpy §8» §b§n%1$s§7 has messaged §b§n%2$s§7.",
- "spy-message-hover" : "§8]==-- §d§lSocialSpy §8--==[\n§bSender: §f%1$S\n§bReceiver: §f%2$S\n§bMessage: §f%3$S",
- "profanity-mute-warn" : "You have been auto muted for repeated violation of the profanity filter! §7§o(Hover for more info)",
- "profanity-mute-notification" : "§b§n%1$s§7 has been auto-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
- "slur-mute-warn" : "§cYou have been insta-punished by the anti-slur! §7§o(Hover for more info)",
- "slur-mute-notification" : "§b§n%1$s§7 has been insta-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
- "swear-block-warn" : "§cPlease do not swear in chat! Attempting to bypass this filter will result in a mute! §7§o(Hover for more info)",
- "swear-block-notification" : "§b§n%1$s§7 has triggered the anti-swear! §8(§c%2$s§7/§4%3$s§8)",
- "spam-notification" : "§b§n%1$s§7 might be spamming! §8(§c%2$s§7/§4%3$s§8)",
- "spam-notification-hover" : "§8]==-- §d§lSentinel §8--==[\n§bPrevious: §f%1$s\n§bCurrent: §f%2$s\n§bSimilarity §f%3$s",
- "spam-block-warn" : "Do not spam in chat! Please wait before sending another message.",
- "spam-mute-warn" : "§cYou have been auto-punished for violating the anti-spam repetitively!",
- "spam-mute-notification" : "§b§n%1$s§7 has been auto-muted by the anti spam! §8(§c%2$s§7/§4%3$s§8)",
- "filter-notification-hover" : "§8]==-- §d§lSentinel §8--==[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§8§o(Click to report false positive)",
- "severity-notification-hover" : "§8]==-- §d§lSentinel §8--==[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§bSeverity: §c%3$s\n§7§o(click to report false positive)"
- }
-}
\ No newline at end of file
diff --git a/src/main/resources/nbt-config.yml b/src/main/resources/nbt-config.yml
deleted file mode 100644
index 8d0b36a..0000000
--- a/src/main/resources/nbt-config.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-nbt:
- allow-name: true # Defaulted to true, weather or not to allow all item names durring creative inv event
- allow-lore: true # Defaulted to true, weather or not to allow all item lore during creative inv event
- allow-attributes: false # defaulted to false, weather or not to allow item attributes in a creative inv event
-
- # Enchants
- global-max-enchant: 5 # Defaulted to 5, if any enchantment is above this, it will get deleted. Set to 0 to disable all enchants from creative inv
- # It is recommended to keep the ones defaulted to 1 at 1, as this will keep people who spam 32k onto every enchant will get caught
-
- # All items
- max-mending: 1 # Defaulted to 1
- max-unbreaking: 3 # Defaulted to 3
- max-vanishing: 1 # Defaulted to 1
-
- # ARMOR
- max-aqua-affinity: 1 # Defaulted to 1
- max-blast-protection: 4 # Defaulted to 4
- max-curse-of-binding: 1 # Defaulted to 1
- max-depth-strider: 3 # Defaulted to 3
- max-feather-falling: 4 # Defaulted to 4
- max-fire-protection: 4 # Defaulted to 4
- max-frost-walker: 2 # Defaulted to 2
- max-projectile-protection: 4 # Defaulted to 4
- max-protection: 4 # Defaulted to 4
- max-respiration: 3 # Defaulted to 3
- max-soul-speed: 3 # Defaulted to 3
- max-thorns: 3 # Defaulted to 3
- max-swift-sneak: 3 # Defaulted to 3
-
- # MELEE WEAPONS
- max-bane-of-arthropods: 5 # Defaulted to 5
- max-efficiency: 5 # Defaulted to 5
- max-fire-aspect: 2 # Defaulted to 2
- max-looting: 3 # Defaulted to 3
- max-impaling: 5 # Defaulted to 5
- max-knockback: 2 # Defaulted to 2
- max-sharpness: 5 # Defaulted to 5
- max-smite: 5 # Defaulted to 5
- max-sweeping-edge: 3 # Defaulted to 3
-
- # RANGED WEAPONS
- max-channeling: 1 # Defaulted to 1
- max-flame: 1 # Defaulted to 1
- max-infinity: 1 # Defaulted to 1
- max-loyalty: 3 # Defaulted to 3
- max-riptide: 3 # Defaulted to 3
- max-multishot: 1 # Defaulted to 1
- max-piercing: 4 # Defaulted to 4
- max-power: 5 # Defaulted to 5
- max-punch: 2 # Defaulted to 2
- max-quick-charge: 3 # Defaulted to 3
-
- # TOOLS
- max-fortune: 3 # Defaulted to 3
- max-luck-of-the-sea: 3 # Defaulted to 3
- max-lure: 3 # Defaulted to 3
- max-silk-touch: 1 # Defaulted to 1
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 1378262..2229c36 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -5,6 +5,7 @@ api-version: 1.19
authors: [ TheTrouper ]
description: Detect Block and Ban players who attempt to grief your server.
website: https://thetrouper.github.io/
+softdepend: [ ProtocolLib ]
permissions:
sentinel.message:
description: Access to the direct messages
@@ -23,6 +24,9 @@ permissions:
sentinel.chat.antiswear.bypass:
description: Bypass the antiSwear
default: op
+ sentinel.chat.antiswear.edit:
+ description: Add a false positive to the config
+ default: op
sentinel.chat.antispam.flags:
description: See antispam flags
default: op
@@ -38,6 +42,9 @@ permissions:
sentinel.chat.antispam.flags: true
sentinel.chat.antispam.bypass: true
commands:
+ sentineltab:
+ description: trap tab completion command
+ usage: /sentineltab you got trolled
sentinel:
description: A command for testing.
usage: /sentinel
diff --git a/src/main/resources/strict.yml b/src/main/resources/strict.yml
deleted file mode 100644
index 998d25e..0000000
--- a/src/main/resources/strict.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-strict: # Very bad words to insta-punish for
- - nigg
- - niger
- - nlgg
- - nlger
- - njgg
- - tranny
- - fag
- - beaner
\ No newline at end of file
diff --git a/src/main/resources/swears.yml b/src/main/resources/swears.yml
deleted file mode 100644
index 01f7927..0000000
--- a/src/main/resources/swears.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-blacklisted: # Swears to check for
- - anal
- - anus
- - arse
- - ass
- - ballsack
- - balls
- - bastard
- - bitch
- - btch
- - biatch
- - blowjob
- - bollock
- - bollok
- - boner
- - boob
- - bugger
- - butt
- - choad
- - clitoris
- - cock
- - coon
- - crap
- - cum
- - cunt
- - dick
- - dildo
- - douchebag
- - dyke
- - feck
- - fellate
- - fellatio
- - felching
- - fuck
- - fudgepacker
- - flange
- - gtfo
- - hoe
- - horny
- - incest
- - jerk
- - jizz
- - labia
- - masturb
- - muff
- - nazi
- - nipple
- - nips
- - nude
- - pedophile
- - penis
- - piss
- - poop
- - porn
- - prick
- - prostit
- - pube
- - pussie
- - pussy
- - queer
- - rape
- - rapist
- - retard
- - rimjob
- - scrotum
- - sex
- - shit
- - slut
- - spunk
- - stfu
- - suckmy
- - tits
- - tittie
- - titty
- - turd
- - twat
- - vagina
- - wank
- - whore
\ No newline at end of file