diff --git a/.gradle/8.12/checksums/checksums.lock b/.gradle/8.12/checksums/checksums.lock new file mode 100644 index 0000000..7df35ae Binary files /dev/null and b/.gradle/8.12/checksums/checksums.lock differ diff --git a/.gradle/8.12/checksums/md5-checksums.bin b/.gradle/8.12/checksums/md5-checksums.bin new file mode 100644 index 0000000..e69b641 Binary files /dev/null and b/.gradle/8.12/checksums/md5-checksums.bin differ diff --git a/.gradle/8.12/checksums/sha1-checksums.bin b/.gradle/8.12/checksums/sha1-checksums.bin new file mode 100644 index 0000000..74a6969 Binary files /dev/null and b/.gradle/8.12/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.12/executionHistory/executionHistory.bin b/.gradle/8.12/executionHistory/executionHistory.bin new file mode 100644 index 0000000..46bb097 Binary files /dev/null and b/.gradle/8.12/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.12/executionHistory/executionHistory.lock b/.gradle/8.12/executionHistory/executionHistory.lock new file mode 100644 index 0000000..63b4f05 Binary files /dev/null and b/.gradle/8.12/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.12/fileChanges/last-build.bin b/.gradle/8.12/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/8.12/fileChanges/last-build.bin differ diff --git a/.gradle/8.12/fileHashes/fileHashes.bin b/.gradle/8.12/fileHashes/fileHashes.bin new file mode 100644 index 0000000..39baf8f Binary files /dev/null and b/.gradle/8.12/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.12/fileHashes/fileHashes.lock b/.gradle/8.12/fileHashes/fileHashes.lock new file mode 100644 index 0000000..e36d0e0 Binary files /dev/null and b/.gradle/8.12/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.12/fileHashes/resourceHashesCache.bin b/.gradle/8.12/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..d62eefa Binary files /dev/null and b/.gradle/8.12/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/8.12/gc.properties b/.gradle/8.12/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..90c493c Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..507882f --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Tue May 27 16:38:57 BST 2025 +gradle.version=8.12 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..a70a0e2 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe new file mode 100644 index 0000000..b573649 Binary files /dev/null and b/.gradle/file-system.probe differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..d0700b4 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..4a2aa3a --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..9dc782b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ 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/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..389e93e --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + 1748302633990 + + + + \ No newline at end of file diff --git a/GeyserModelEngine.iml b/GeyserModelEngine.iml deleted file mode 100644 index d913b81..0000000 --- a/GeyserModelEngine.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - PAPER - ADVENTURE - - - - - - - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..77eeaf6 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,60 @@ +plugins { + id("java") + id("io.github.goooler.shadow") version "8.1.7" +} + +group = "re.imc" +version = "1.0.0" + +repositories { + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") + + maven("https://mvn.lumine.io/repository/maven-public/") + + maven("https://repo.opencollab.dev/maven-releases/") { + isAllowInsecureProtocol = true + } + maven("https://repo.opencollab.dev/maven-snapshots/") { + isAllowInsecureProtocol = true + } + + maven("https://repo.codemc.io/repository/maven-public/") + maven("https://repo.codemc.io/repository/maven-releases/") +} + +dependencies { + compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") + + implementation("dev.jorel:commandapi-bukkit-shade-mojang-mapped:10.0.1") + + compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.4") + compileOnly(files("libs/geyserutils-spigot-1.0-SNAPSHOT.jar")) + compileOnly("org.geysermc.floodgate:api:2.2.2-SNAPSHOT") + + implementation("com.github.retrooper:packetevents-spigot:2.8.0") + + implementation("org.reflections:reflections:0.10.2") +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} + +tasks.compileJava { + options.encoding = "UTF-8" +} + +tasks.shadowJar { + relocate("dev.jorel.commandapi", "re.imc.geysermodelengine.libs.commandapi") + + relocate("com.github.retrooper", "re.imc.geysermodelengine.libs.com.github.retrooper.packetevents") + relocate("io.github.retrooper", "re.imc.geysermodelengine.libs.io.github.retrooper.packetevents") + + relocate("org.reflections", "re.imc.geysermodelengine.libs.reflections") +} + +tasks.jar { + dependsOn(tasks.shadowJar) +} \ No newline at end of file diff --git a/build/classes/java/main/re/imc/geysermodelengine/GeyserModelEngine.class b/build/classes/java/main/re/imc/geysermodelengine/GeyserModelEngine.class new file mode 100644 index 0000000..96f94f3 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/GeyserModelEngine.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.class b/build/classes/java/main/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.class new file mode 100644 index 0000000..d0dfc7e Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/listener/ModelListener.class b/build/classes/java/main/re/imc/geysermodelengine/listener/ModelListener.class new file mode 100644 index 0000000..feaad3b Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/listener/ModelListener.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/listener/MountPacketListener.class b/build/classes/java/main/re/imc/geysermodelengine/listener/MountPacketListener.class new file mode 100644 index 0000000..779c016 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/listener/MountPacketListener.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/ConfigManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/ConfigManager.class new file mode 100644 index 0000000..dc9ab0a Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/ConfigManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.class new file mode 100644 index 0000000..74586e4 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManager.class new file mode 100644 index 0000000..ca8f636 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManagers.class b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManagers.class new file mode 100644 index 0000000..2d0cc12 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/CommandManagers.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.class new file mode 100644 index 0000000..41bb32e Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.class b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.class new file mode 100644 index 0000000..01cd174 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/model/EntityTaskManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/model/EntityTaskManager.class new file mode 100644 index 0000000..2a5e04c Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/model/EntityTaskManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/model/ModelManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/model/ModelManager.class new file mode 100644 index 0000000..0fc48c2 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/model/ModelManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/model/data/ModelEntityData.class b/build/classes/java/main/re/imc/geysermodelengine/managers/model/data/ModelEntityData.class new file mode 100644 index 0000000..ee46170 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/model/data/ModelEntityData.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/player/PlayerManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/player/PlayerManager.class new file mode 100644 index 0000000..d9fc723 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/player/PlayerManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerData.class b/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerData.class new file mode 100644 index 0000000..9c2f448 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerData.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerManager.class b/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerManager.class new file mode 100644 index 0000000..977adf5 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/managers/server/ServerManager.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/packet/entity/PacketEntity.class b/build/classes/java/main/re/imc/geysermodelengine/packet/entity/PacketEntity.class new file mode 100644 index 0000000..ca5d881 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/packet/entity/PacketEntity.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.class b/build/classes/java/main/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.class new file mode 100644 index 0000000..b3ca4c0 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/runnables/EntityTaskRunnable.class b/build/classes/java/main/re/imc/geysermodelengine/runnables/EntityTaskRunnable.class new file mode 100644 index 0000000..1d33c4d Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/runnables/EntityTaskRunnable.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.class b/build/classes/java/main/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.class new file mode 100644 index 0000000..692d904 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/util/BooleanPacker.class b/build/classes/java/main/re/imc/geysermodelengine/util/BooleanPacker.class new file mode 100644 index 0000000..777b201 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/util/BooleanPacker.class differ diff --git a/build/classes/java/main/re/imc/geysermodelengine/util/ColourUtils.class b/build/classes/java/main/re/imc/geysermodelengine/util/ColourUtils.class new file mode 100644 index 0000000..e542e09 Binary files /dev/null and b/build/classes/java/main/re/imc/geysermodelengine/util/ColourUtils.class differ diff --git a/build/libs/GeyserModelEngine-1.0.0-all.jar b/build/libs/GeyserModelEngine-1.0.0-all.jar new file mode 100644 index 0000000..da31d7d Binary files /dev/null and b/build/libs/GeyserModelEngine-1.0.0-all.jar differ diff --git a/build/libs/GeyserModelEngine-1.0.0.jar b/build/libs/GeyserModelEngine-1.0.0.jar new file mode 100644 index 0000000..ff24642 Binary files /dev/null and b/build/libs/GeyserModelEngine-1.0.0.jar differ diff --git a/build/reports/problems/problems-report.html b/build/reports/problems/problems-report.html new file mode 100644 index 0000000..d6f75ed --- /dev/null +++ b/build/reports/problems/problems-report.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/build/resources/main/Lang/messages.yml b/build/resources/main/Lang/messages.yml new file mode 100644 index 0000000..fdc999a --- /dev/null +++ b/build/resources/main/Lang/messages.yml @@ -0,0 +1,4 @@ + +commands: + reload: + successfully-reloaded: "<#55FF55>GeyserModelEngine configuration reloaded!" \ No newline at end of file diff --git a/build/resources/main/config.yml b/build/resources/main/config.yml new file mode 100644 index 0000000..ba9fd1e --- /dev/null +++ b/build/resources/main/config.yml @@ -0,0 +1,8 @@ +data-send-delay: 5 +entity-view-distance: 50 +join-send-delay: 20 +entity-position-update-period: 35 +model-entity-type: BAT # must be a living entity +enable-part-visibility-models: + - example +debug: false \ No newline at end of file diff --git a/build/resources/main/paper-plugin.yml b/build/resources/main/paper-plugin.yml new file mode 100644 index 0000000..5a771d5 --- /dev/null +++ b/build/resources/main/paper-plugin.yml @@ -0,0 +1,18 @@ +main: re.imc.geysermodelengine.GeyserModelEngine +name: GeyserModelEngine +version: '1.0.0' +api-version: '1.21' + +authors: + - zimzaza4 + - willem.dev + - TheLividaProject + +dependencies: + server: + packetevents: + required: true + ModelEngine: + required: true + floodgate: + required: true \ No newline at end of file diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/BedrockMountControlRunnable.class.uniqueId12 b/build/tmp/compileJava/compileTransaction/stash-dir/BedrockMountControlRunnable.class.uniqueId12 new file mode 100644 index 0000000..b3ca4c0 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/BedrockMountControlRunnable.class.uniqueId12 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/CommandManager.class.uniqueId11 b/build/tmp/compileJava/compileTransaction/stash-dir/CommandManager.class.uniqueId11 new file mode 100644 index 0000000..ca8f636 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/CommandManager.class.uniqueId11 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/ConfigManager.class.uniqueId9 b/build/tmp/compileJava/compileTransaction/stash-dir/ConfigManager.class.uniqueId9 new file mode 100644 index 0000000..dc9ab0a Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/ConfigManager.class.uniqueId9 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskManager.class.uniqueId5 b/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskManager.class.uniqueId5 new file mode 100644 index 0000000..cf01e52 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskManager.class.uniqueId5 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskRunnable.class.uniqueId10 b/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskRunnable.class.uniqueId10 new file mode 100644 index 0000000..1d33c4d Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/EntityTaskRunnable.class.uniqueId10 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngine.class.uniqueId0 b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngine.class.uniqueId0 new file mode 100644 index 0000000..96f94f3 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngine.class.uniqueId0 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineCommandManager.class.uniqueId3 b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineCommandManager.class.uniqueId3 new file mode 100644 index 0000000..41bb32e Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineCommandManager.class.uniqueId3 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineReloadCommand.class.uniqueId1 b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineReloadCommand.class.uniqueId1 new file mode 100644 index 0000000..d0dfc7e Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/GeyserModelEngineReloadCommand.class.uniqueId1 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/ModelEntityData.class.uniqueId7 b/build/tmp/compileJava/compileTransaction/stash-dir/ModelEntityData.class.uniqueId7 new file mode 100644 index 0000000..ee46170 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/ModelEntityData.class.uniqueId7 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/ModelListener.class.uniqueId2 b/build/tmp/compileJava/compileTransaction/stash-dir/ModelListener.class.uniqueId2 new file mode 100644 index 0000000..feaad3b Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/ModelListener.class.uniqueId2 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/ModelManager.class.uniqueId8 b/build/tmp/compileJava/compileTransaction/stash-dir/ModelManager.class.uniqueId8 new file mode 100644 index 0000000..0fc48c2 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/ModelManager.class.uniqueId8 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/MountPacketListener.class.uniqueId6 b/build/tmp/compileJava/compileTransaction/stash-dir/MountPacketListener.class.uniqueId6 new file mode 100644 index 0000000..779c016 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/MountPacketListener.class.uniqueId6 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/UpdateTaskRunnable.class.uniqueId4 b/build/tmp/compileJava/compileTransaction/stash-dir/UpdateTaskRunnable.class.uniqueId4 new file mode 100644 index 0000000..692d904 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/UpdateTaskRunnable.class.uniqueId4 differ diff --git a/build/tmp/compileJava/previous-compilation-data.bin b/build/tmp/compileJava/previous-compilation-data.bin new file mode 100644 index 0000000..f26b533 Binary files /dev/null and b/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/build/tmp/shadowJar/MANIFEST.MF b/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cea7a79 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..f3b75f3 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 48b716b..0000000 --- a/pom.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - 4.0.0 - - re.imc - GeyserModelEngine - 1.0-SNAPSHOT - jar - - GeyserModelEngine - - - 1.8 - UTF-8 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 16 - 16 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.4.1 - - - - com.github.retrooper.packetevents - re.imc.geysermodelengine.libs.com.github.retrooper.packetevents - - - io.github.retrooper.packetevents - re.imc.geysermodelengine.libs.io.github.retrooper.packetevents - - - - - - package - - shade - - - false - - - - - - - - src/main/resources - true - - - - - - - papermc-repo - https://repo.papermc.io/repository/maven-public/ - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - - nexus - Lumine Public - https://mvn.lumine.io/repository/maven-public/ - - - md_5-public - https://repo.md-5.net/content/groups/public/ - - - opencollab-release-repo - https://repo.opencollab.dev/maven-releases/ - - true - - - true - - - - opencollab-snapshot-repo - https://repo.opencollab.dev/maven-snapshots/ - - false - - - true - - - - dmulloy2-repo - https://repo.dmulloy2.net/repository/public/ - - - codemc-releases - https://repo.codemc.io/repository/maven-releases/ - - - codemc-snapshots - https://repo.codemc.io/repository/maven-snapshots/ - - - - - - io.papermc.paper - paper-api - 1.21.5-R0.1-SNAPSHOT - provided - - - com.ticxo.modelengine - ModelEngine - R4.0.4 - provided - - - com.github.geyserextensionists - geyserutils-spigot - 1.0.0 - system - ${project.basedir}/libs/geyserutils-spigot-1.0-SNAPSHOT.jar - - - org.geysermc.floodgate - api - 2.2.2-SNAPSHOT - provided - - - com.github.retrooper - packetevents-spigot - 2.8.0 - compile - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..8e9efd7 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "GeyserModelEngine" + diff --git a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java index 1f0735a..25ea6f5 100644 --- a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java +++ b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java @@ -2,149 +2,143 @@ package re.imc.geysermodelengine; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.event.PacketListenerPriority; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import com.ticxo.modelengine.api.ModelEngineAPI; import com.ticxo.modelengine.api.model.ActiveModel; import com.ticxo.modelengine.api.model.ModeledEntity; -import com.ticxo.modelengine.api.model.bone.type.Mount; +import dev.jorel.commandapi.CommandAPI; +import dev.jorel.commandapi.CommandAPIBukkitConfig; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import lombok.Getter; -import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; -import re.imc.geysermodelengine.commands.ReloadCommand; import re.imc.geysermodelengine.listener.ModelListener; import re.imc.geysermodelengine.listener.MountPacketListener; -import re.imc.geysermodelengine.model.BedrockMountControl; -import re.imc.geysermodelengine.model.ModelEntity; +import re.imc.geysermodelengine.managers.ConfigManager; +import re.imc.geysermodelengine.managers.bedrock.BedrockMountControlManager; +import re.imc.geysermodelengine.managers.commands.CommandManager; +import re.imc.geysermodelengine.managers.model.EntityTaskManager; +import re.imc.geysermodelengine.managers.model.ModelManager; +import re.imc.geysermodelengine.managers.player.PlayerManager; +import re.imc.geysermodelengine.managers.server.ServerManager; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; +import re.imc.geysermodelengine.runnables.BedrockMountControlRunnable; +import re.imc.geysermodelengine.runnables.UpdateTaskRunnable; import java.util.*; import java.util.concurrent.*; -public final class GeyserModelEngine extends JavaPlugin { +public class GeyserModelEngine extends JavaPlugin { - @Getter - private static GeyserModelEngine instance; + private ConfigManager configManager; + private ServerManager serverManager; - @Getter - private static boolean alwaysSendSkin; + private CommandManager commandManager; - @Getter - private int sendDelay; + private ModelManager modelManager; + private EntityTaskManager entityTaskManager; + private BedrockMountControlManager bedrockMountControlManager; - @Getter - private int viewDistance; - - @Getter - private Set joinedPlayers = new HashSet<>(); - - @Getter - private int joinSendDelay; - - @Getter - private long entityPositionUpdatePeriod; - - @Getter - private boolean debug; - - @Getter - private Map> drivers = new ConcurrentHashMap<>(); - - @Getter - private boolean initialized = false; - - @Getter - private List enablePartVisibilityModels = new ArrayList<>(); - - @Getter - private ScheduledExecutorService scheduler; - private ScheduledFuture updateTask; + private PlayerManager playerManager; @Override public void onLoad() { PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); PacketEvents.getAPI().load(); + + CommandAPI.onLoad(new CommandAPIBukkitConfig(this)); } @Override public void onEnable() { - PacketEvents.getAPI().init(); - PacketEvents.getAPI().getEventManager().registerListener(new MountPacketListener(), PacketListenerPriority.NORMAL); - /* - scheduler.scheduleAtFixedRate(() -> { - try { - for (Map models : ModelEntity.ENTITIES.values()) { - models.values().forEach(ModelEntity::teleportToModel); - } - } catch (Throwable t) { - t.printStackTrace(); - } - }, 10, entityPositionUpdatePeriod, TimeUnit.MILLISECONDS); + loadHooks(); + loadManagers(); + loadRunnables(); - */ + PacketEvents.getAPI().getEventManager().registerListener(new MountPacketListener(this), PacketListenerPriority.NORMAL); - reload(); - getCommand("geysermodelengine").setExecutor(new ReloadCommand(this)); - Bukkit.getPluginManager().registerEvents(new ModelListener(), this); - Bukkit.getScheduler() - .runTaskLater(GeyserModelEngine.getInstance(), () -> { + Bukkit.getPluginManager().registerEvents(new ModelListener(this), this); + + Bukkit.getScheduler().runTaskLater(this, () -> { for (World world : Bukkit.getWorlds()) { + for (Entity entity : world.getEntities()) { - if (!ModelEntity.ENTITIES.containsKey(entity.getEntityId())) { + + if (!modelManager.getEntitiesCache().containsKey(entity.getEntityId())) { + ModeledEntity modeledEntity = ModelEngineAPI.getModeledEntity(entity); + if (modeledEntity != null) { Optional model = modeledEntity.getModels().values().stream().findFirst(); - model.ifPresent(m -> ModelEntity.create(modeledEntity, m)); + model.ifPresent(m -> modelManager.create(modeledEntity, m)); } } } } - initialized = true; - }, 100); - - - BedrockMountControl.startTask(); - } - - public void reload() { - saveDefaultConfig(); - // alwaysSendSkin = getConfig().getBoolean("always-send-skin"); - sendDelay = getConfig().getInt("data-send-delay", 5); - scheduler = Executors.newScheduledThreadPool(getConfig().getInt("thread-pool-size", 4)); - viewDistance = getConfig().getInt("entity-view-distance", 60); - debug = getConfig().getBoolean("debug", false); - joinSendDelay = getConfig().getInt("join-send-delay", 20); - entityPositionUpdatePeriod = getConfig().getLong("entity-position-update-period", 35); - enablePartVisibilityModels.addAll(getConfig().getStringList("enable-part-visibility-models")); - - instance = this; - if (updateTask != null) updateTask.cancel(true); - - updateTask = scheduler.scheduleWithFixedDelay(() -> { - try { - for (Map models : ModelEntity.ENTITIES.values()) { - models.values().forEach(model -> model.getTask().updateEntityProperties(model.getViewers(), false)); - } - } catch (Throwable err) { - throw new RuntimeException(err); - } - }, 10, entityPositionUpdatePeriod, TimeUnit.MILLISECONDS); } @Override public void onDisable() { PacketEvents.getAPI().terminate(); - for (Map entities : ModelEntity.ENTITIES.values()) { + + for (Map entities : modelManager.getEntitiesCache().values()) { entities.forEach((model, modelEntity) -> { modelEntity.getEntity().remove(); }); } - // Plugin shutdown logic + + CommandAPI.onDisable(); } + private void loadHooks() { + PacketEvents.getAPI().init(); + CommandAPI.onEnable(); + } + + private void loadManagers() { + this.configManager = new ConfigManager(this); + this.serverManager = new ServerManager(); + + this.commandManager = new CommandManager(this); + + this.modelManager = new ModelManager(this); + this.entityTaskManager = new EntityTaskManager(this); + this.bedrockMountControlManager = new BedrockMountControlManager(); + + this.playerManager = new PlayerManager(); + } + + private void loadRunnables() { + Bukkit.getAsyncScheduler().runAtFixedRate(this, new UpdateTaskRunnable(this), 10, configManager.getConfig().getLong("entity-position-update-period"), TimeUnit.MILLISECONDS); + Bukkit.getAsyncScheduler().runAtFixedRate(this, new BedrockMountControlRunnable(this), 1, 1, TimeUnit.MILLISECONDS); + } + + public ConfigManager getConfigManager() { + return configManager; + } + + public ServerManager getServerManager() { + return serverManager; + } + + public CommandManager getCommandManager() { + return commandManager; + } + + public ModelManager getModelManager() { + return modelManager; + } + + public EntityTaskManager getEntityTaskManager() { + return entityTaskManager; + } + + public BedrockMountControlManager getBedrockMountControlManager() { + return bedrockMountControlManager; + } + + public PlayerManager getPlayerManager() { + return playerManager; + } } diff --git a/src/main/java/re/imc/geysermodelengine/commands/ReloadCommand.java b/src/main/java/re/imc/geysermodelengine/commands/ReloadCommand.java deleted file mode 100644 index 418b640..0000000 --- a/src/main/java/re/imc/geysermodelengine/commands/ReloadCommand.java +++ /dev/null @@ -1,31 +0,0 @@ -package re.imc.geysermodelengine.commands; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import re.imc.geysermodelengine.GeyserModelEngine; - -public class ReloadCommand implements CommandExecutor { - - private final GeyserModelEngine plugin; - - public ReloadCommand(GeyserModelEngine plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - - if (sender instanceof Player && !sender.hasPermission("geysermodelengine.reload")) { - sender.sendMessage("§cYou don't have permission to use this command."); - return true; - } - - plugin.reloadConfig(); - plugin.reload(); - - sender.sendMessage("§aGeyserModelEngine configuration reloaded!"); - return true; - } -} \ No newline at end of file diff --git a/src/main/java/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.java b/src/main/java/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.java new file mode 100644 index 0000000..628fca1 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/commands/geysermodelenginecommands/GeyserModelEngineReloadCommand.java @@ -0,0 +1,31 @@ +package re.imc.geysermodelengine.commands.geysermodelenginecommands; + +import dev.jorel.commandapi.CommandAPICommand; +import org.bukkit.Bukkit; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands; +import re.imc.geysermodelengine.util.ColourUtils; + +public class GeyserModelEngineReloadCommand implements SubCommands { + + private final GeyserModelEngine plugin; + + private final ColourUtils colourUtils = new ColourUtils(); + + public GeyserModelEngineReloadCommand(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + @Override + public CommandAPICommand onCommand() { + return new CommandAPICommand("reload") + .withPermission("geysermodelengine.commands.reload") + .executes((sender, args) -> { + Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> { + plugin.getConfigManager().load(); + }); + + sender.sendMessage(colourUtils.miniFormat(plugin.getConfigManager().getLang().getString("commands.reload.successfully-reloaded"))); + }); + } +} \ No newline at end of file diff --git a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java index d06f180..519e4ff 100644 --- a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java +++ b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java @@ -3,7 +3,6 @@ package re.imc.geysermodelengine.listener; import com.ticxo.modelengine.api.events.AddModelEvent; import com.ticxo.modelengine.api.events.ModelDismountEvent; import com.ticxo.modelengine.api.events.ModelMountEvent; -import com.ticxo.modelengine.api.events.RemoveModelEvent; import com.ticxo.modelengine.api.model.ActiveModel; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; @@ -12,117 +11,54 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.model.ModelEntity; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; import java.util.Map; public class ModelListener implements Listener { - @EventHandler(priority = EventPriority.MONITOR) - public void onAddModel(AddModelEvent event) { - if (event.isCancelled()) { - return; - } + private final GeyserModelEngine plugin; - if (!GeyserModelEngine.getInstance().isInitialized()) { - return; - } - ModelEntity.create(event.getTarget(), event.getModel()); + public ModelListener(GeyserModelEngine plugin) { + this.plugin = plugin; } + @EventHandler(priority = EventPriority.MONITOR) + public void onAddModel(AddModelEvent event) { + if (event.isCancelled()) return; - @EventHandler - public void onRemoveModel(RemoveModelEvent event) { + plugin.getModelManager().create(event.getTarget(), event.getModel()); } @EventHandler(priority = EventPriority.MONITOR) public void onModelMount(ModelMountEvent event) { - Map map = ModelEntity.ENTITIES.get(event.getVehicle().getModeledEntity().getBase().getEntityId()); - if (map == null) { - } - if (!event.isDriver()) { - return; - } - ModelEntity model = map.get(event.getVehicle()); + Map map = plugin.getModelManager().getEntitiesCache().get(event.getVehicle().getModeledEntity().getBase().getEntityId()); + if (!event.isDriver()) return; + + ModelEntityData model = map.get(event.getVehicle()); if (model != null && event.getPassenger() instanceof Player player) { - GeyserModelEngine.getInstance().getDrivers().put(player, Pair.of(event.getVehicle(), event.getSeat())); + plugin.getBedrockMountControlManager().getDriversCache().put(player, Pair.of(event.getVehicle(), event.getSeat())); } } @EventHandler(priority = EventPriority.MONITOR) public void onModelDismount(ModelDismountEvent event) { if (event.getPassenger() instanceof Player player) { - GeyserModelEngine.getInstance().getDrivers().remove(player); + plugin.getBedrockMountControlManager().getDriversCache().remove(player); } } - - - - - - /* - @EventHandler(priority = EventPriority.MONITOR) - public void onModelEntityHurt(EntityDamageEvent event) { - if (event.isCancelled()) { - return; - } - - Map model = ModelEntity.ENTITIES.get(event.getEntity().getEntityId()); - if (model != null) { - for (Map.Entry entry : model.entrySet()) { - if (!entry.getValue().getEntity().isDead()) { - //entry.getValue().getEntity().sendHurtPacket(entry.getValue().getViewers()); - } - } - - } - } - - - /* - - @EventHandler - public void onModelAttack(EntityDamageByEntityEvent event) { - ModelEntity model = ModelEntity.ENTITIES.get(event.getDamager().getEntityId()); - if (model != null) { - EntityTask task = model.getTask(); - - task.playAnimation("attack", 55); - } - }| - - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onAnimationPlay(AnimationPlayEvent event) { - Map map = ModelEntity.ENTITIES.get(event.getModel().getModeledEntity().getBase().getEntityId()); - if (map == null) { - return; - } - - ModelEntity model = map.get(event.getModel()); - model.getTask().updateEntityProperties(model.getViewers(), false, event.getProperty().getName()); - } - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onAnimationEnd(AnimationEndEvent event) { - Map map = ModelEntity.ENTITIES.get(event.getModel().getModeledEntity().getBase().getEntityId()); - if (map == null) { - return; - } - - ModelEntity model = map.get(event.getModel()); - model.getTask().updateEntityProperties(model.getViewers(), false, event.getProperty().); - } - */ + //TODO Find out why we need this bc uh what? @EventHandler public void onPlayerLogin(PlayerJoinEvent event) { - Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> GeyserModelEngine.getInstance().getJoinedPlayers().add(event.getPlayer()), 10); + Bukkit.getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> plugin.getPlayerManager().getPlayerJoinedCache().add(event.getPlayer()), 10); } + @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> GeyserModelEngine.getInstance().getJoinedPlayers().remove(event.getPlayer()), 10); + Bukkit.getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> plugin.getPlayerManager().getPlayerJoinedCache().remove(event.getPlayer()), 10); } } diff --git a/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java b/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java index 6f83e35..43dafe0 100644 --- a/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java +++ b/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java @@ -14,6 +14,12 @@ import re.imc.geysermodelengine.GeyserModelEngine; public class MountPacketListener implements PacketListener { + private final GeyserModelEngine plugin; + + public MountPacketListener(GeyserModelEngine plugin) { + this.plugin = plugin; + } + @Override public void onPacketReceive(PacketReceiveEvent event) { if (event.getPacketType() != PacketType.Play.Client.ENTITY_ACTION) return; @@ -22,7 +28,7 @@ public class MountPacketListener implements PacketListener { Player player = event.getPlayer(); WrapperPlayClientEntityAction action = new WrapperPlayClientEntityAction(event); - Pair seat = GeyserModelEngine.getInstance().getDrivers().get(player); + Pair seat = plugin.getBedrockMountControlManager().getDriversCache().get(player); if (seat == null) return; if (action.getAction() != WrapperPlayClientEntityAction.Action.START_SNEAKING) return; diff --git a/src/main/java/re/imc/geysermodelengine/managers/ConfigManager.java b/src/main/java/re/imc/geysermodelengine/managers/ConfigManager.java new file mode 100644 index 0000000..0d1d8c0 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/ConfigManager.java @@ -0,0 +1,32 @@ +package re.imc.geysermodelengine.managers; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import re.imc.geysermodelengine.GeyserModelEngine; + +import java.io.File; + +public class ConfigManager { + + private final GeyserModelEngine plugin; + + private FileConfiguration config, lang; + + public ConfigManager(GeyserModelEngine plugin) { + this.plugin = plugin; + load(); + } + + public void load() { + this.config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "config.yml")); + this.lang = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "Lang/messages.yml")); + } + + public FileConfiguration getConfig() { + return config; + } + + public FileConfiguration getLang() { + return lang; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.java b/src/main/java/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.java new file mode 100644 index 0000000..74e1917 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/bedrock/BedrockMountControlManager.java @@ -0,0 +1,17 @@ +package re.imc.geysermodelengine.managers.bedrock; + +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.bone.type.Mount; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.entity.Player; + +import java.util.concurrent.ConcurrentHashMap; + +public class BedrockMountControlManager { + + private final ConcurrentHashMap> driversCache = new ConcurrentHashMap<>(); + + public ConcurrentHashMap> getDriversCache() { + return driversCache; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManager.java b/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManager.java new file mode 100644 index 0000000..fe46a7a --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManager.java @@ -0,0 +1,36 @@ +package re.imc.geysermodelengine.managers.commands; + +import org.reflections.Reflections; +import re.imc.geysermodelengine.GeyserModelEngine; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + +public class CommandManager { + + private final GeyserModelEngine plugin; + + private final HashMap commandManagersCache = new HashMap<>(); + + public CommandManager(GeyserModelEngine plugin) { + this.plugin = plugin; + load("re.imc.geysermodelengine.managers.commands.managers"); + } + + private void load(String path) { + for (Class clazz : new Reflections(path).getSubTypesOf(CommandManagers.class)) { + try { + CommandManagers commandManager = (CommandManagers) clazz.getDeclaredConstructor(GeyserModelEngine.class).newInstance(plugin); + plugin.getLogger().warning("Loading Command Manager - " + commandManager.name()); + commandManagersCache.put(commandManager.name(), commandManager); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException err) { + plugin.getLogger().severe("Failed to load Command Manager " + clazz.getName()); + throw new RuntimeException(err); + } + } + } + + public HashMap getCommandManagersCache() { + return commandManagersCache; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManagers.java b/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManagers.java new file mode 100644 index 0000000..d757bbc --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/commands/CommandManagers.java @@ -0,0 +1,12 @@ +package re.imc.geysermodelengine.managers.commands; + +import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands; + +import java.util.ArrayList; + +public interface CommandManagers { + + String name(); + + ArrayList getCommands(); +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.java b/src/main/java/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.java new file mode 100644 index 0000000..3d13b29 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/commands/managers/geysermodelengine/GeyserModelEngineCommandManager.java @@ -0,0 +1,38 @@ +package re.imc.geysermodelengine.managers.commands.managers.geysermodelengine; + +import dev.jorel.commandapi.CommandAPICommand; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.commands.geysermodelenginecommands.GeyserModelEngineReloadCommand; +import re.imc.geysermodelengine.managers.commands.CommandManagers; +import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands; + +import java.util.ArrayList; + +public class GeyserModelEngineCommandManager implements CommandManagers { + + private final ArrayList commands = new ArrayList<>(); + + public GeyserModelEngineCommandManager(GeyserModelEngine plugin) { + commands.add(new GeyserModelEngineReloadCommand(plugin)); + + registerCommand(); + } + + private void registerCommand() { + CommandAPICommand geyserModelEngineCommand = new CommandAPICommand(name()); + + commands.forEach(subCommands -> geyserModelEngineCommand.withSubcommand(subCommands.onCommand())); + + geyserModelEngineCommand.register(); + } + + @Override + public String name() { + return "geysermodelengine"; + } + + @Override + public ArrayList getCommands() { + return commands; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.java b/src/main/java/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.java new file mode 100644 index 0000000..ebdc2a0 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/commands/subcommands/SubCommands.java @@ -0,0 +1,7 @@ +package re.imc.geysermodelengine.managers.commands.subcommands; + +import dev.jorel.commandapi.CommandAPICommand; + +public interface SubCommands { + CommandAPICommand onCommand(); +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java b/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java new file mode 100644 index 0000000..0826b3d --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java @@ -0,0 +1,156 @@ +package re.imc.geysermodelengine.managers.model; + +import com.ticxo.modelengine.api.animation.BlueprintAnimation; +import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.render.DisplayRenderer; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.geysermc.floodgate.api.FloodgateApi; +import org.joml.Vector3fc; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; +import re.imc.geysermodelengine.packet.entity.PacketEntity; +import re.imc.geysermodelengine.runnables.EntityTaskRunnable; + +import java.awt.*; +import java.lang.reflect.Method; +import java.util.*; + +public class EntityTaskManager { + + private final GeyserModelEngine plugin; + + private final Method scaleMethod; + + public EntityTaskManager(GeyserModelEngine plugin) { + this.plugin = plugin; + + try { + this.scaleMethod = ActiveModel.class.getMethod("getScale"); + } catch (NoSuchMethodException err) { + throw new RuntimeException(err); + } + } + + public String unstripName(BlueprintBone bone) { + String name = bone.getName(); + if (bone.getBehaviors().get("head") != null) { + if (!bone.getBehaviors().get("head").isEmpty()) return "hi_" + name; + return "h_" + name; + } + + return name; + } + + public void sendScale(ModelEntityData model, Collection players, float lastScale, boolean firstSend) { + try { + if (players.isEmpty()) return; + + Vector3fc scale = (Vector3fc) scaleMethod.invoke(model.getActiveModel()); + + float average = (scale.x() + scale.y() + scale.z()) / 3; + + if (!firstSend) { + if (average == lastScale) return; + } + + for (Player player : players) { + EntityUtils.sendCustomScale(player, model.getEntity().getEntityId(), average); + } + } catch (Throwable t) { + // ignore + } + } + + public void sendColor(ModelEntityData model, Collection players, Color lastColor, boolean firstSend) { + if (players.isEmpty()) return; + + Color color = new Color(model.getActiveModel().getDefaultTint().asARGB()); + if (model.getActiveModel().isMarkedHurt()) color = new Color(model.getActiveModel().getDamageTint().asARGB()); + + if (firstSend) { + if (color.equals(lastColor)) return; + } + + for (Player player : players) { + EntityUtils.sendCustomColor(player, model.getEntity().getEntityId(), color); + } + } + + public void checkViewers(ModelEntityData model, Set viewers) { + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if (FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) { + + if (canSee(onlinePlayer, model.getEntity())) { + + if (!viewers.contains(onlinePlayer)) { + sendSpawnPacket(model, onlinePlayer); + viewers.add(onlinePlayer); + } + } else { + if (viewers.contains(onlinePlayer)) { + model.getEntity().sendEntityDestroyPacket(Collections.singletonList(onlinePlayer)); + viewers.remove(onlinePlayer); + } + } + } + } + } + + private void sendSpawnPacket(ModelEntityData model, Player onlinePlayer) { + EntityTaskRunnable task = model.getEntityTask(); + boolean firstJoined = !plugin.getPlayerManager().getPlayerJoinedCache().contains(onlinePlayer); + + if (firstJoined) { + task.sendEntityData(model, onlinePlayer, plugin.getConfigManager().getConfig().getInt("join-send-delay") / 50); + } else { + task.sendEntityData(model, onlinePlayer, 5); + } + } + + public boolean canSee(Player player, PacketEntity entity) { + if (!player.isOnline()) return false; + if (!plugin.getPlayerManager().getPlayerJoinedCache().contains(player)) return false; + + Location playerLocation = player.getLocation().clone(); + Location entityLocation = entity.getLocation().clone(); + playerLocation.setY(0); + entityLocation.setY(0); + + if (playerLocation.getWorld() != entityLocation.getWorld()) return false; + if (playerLocation.distanceSquared(entityLocation) > player.getSendViewDistance() * player.getSendViewDistance() * 48) return false; + + return true; + } + + public void sendHitBoxToAll(ModelEntityData model) { + for (Player viewer : model.getViewers()) { + EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.01f, 0.01f); + } + } + + public void sendHitBox(ModelEntityData model, Player viewer) { + float w = 0; + + if (model.getActiveModel().isShadowVisible()) { + if (model.getActiveModel().getModelRenderer() instanceof DisplayRenderer displayRenderer) { + // w = displayRenderer.getHitbox().getShadowRadius().get(); + } + } + + EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.02f, w); + } + + public boolean hasAnimation(ModelEntityData model, String animation) { + ActiveModel activeModel = model.getActiveModel(); + BlueprintAnimation animationProperty = activeModel.getBlueprint().getAnimations().get(animation); + return !(animationProperty == null); + } + + public Method getScaleMethod() { + return scaleMethod; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java b/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java new file mode 100644 index 0000000..f057c09 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java @@ -0,0 +1,46 @@ +package re.imc.geysermodelengine.managers.model; + +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.ModeledEntity; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; +import re.imc.geysermodelengine.runnables.EntityTaskRunnable; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ModelManager { + + private final GeyserModelEngine plugin; + + private final ConcurrentHashMap> entitiesCache = new ConcurrentHashMap<>(); + private final Map modelEntitiesCache = new ConcurrentHashMap<>(); + + public ModelManager(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + public void create(ModeledEntity entity, ActiveModel model) { + ModelEntityData modelEntity = new ModelEntityData(plugin, entity, model); + int id = entity.getBase().getEntityId(); + + Map map = entitiesCache.computeIfAbsent(id, k -> new HashMap<>()); + + for (Map.Entry entry : map.entrySet()) { + if (entry.getKey() != model && entry.getKey().getBlueprint().getName().equals(model.getBlueprint().getName())) { + return; + } + } + + map.put(model, modelEntity); + } + + public ConcurrentHashMap> getEntitiesCache() { + return entitiesCache; + } + + public Map getModelEntitiesCache() { + return modelEntitiesCache; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/data/ModelEntityData.java b/src/main/java/re/imc/geysermodelengine/managers/model/data/ModelEntityData.java new file mode 100644 index 0000000..0dccec4 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/data/ModelEntityData.java @@ -0,0 +1,75 @@ +package re.imc.geysermodelengine.managers.model.data; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.google.common.collect.Sets; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.ModeledEntity; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.packet.entity.PacketEntity; +import re.imc.geysermodelengine.runnables.EntityTaskRunnable; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class ModelEntityData { + + private final GeyserModelEngine plugin; + + private PacketEntity entity; + + private final Set viewers = Sets.newConcurrentHashSet(); + + private final ModeledEntity modeledEntity; + + private final ActiveModel activeModel; + + private EntityTaskRunnable entityTask; + + public ModelEntityData(GeyserModelEngine plugin, ModeledEntity modeledEntity, ActiveModel model) { + this.plugin = plugin; + + this.modeledEntity = modeledEntity; + this.activeModel = model; + this.entity = spawnEntity(); + + runEntityTask(); + } + + public void teleportToModel() { + Location location = modeledEntity.getBase().getLocation(); + entity.teleport(location); + } + + public PacketEntity spawnEntity() { + entity = new PacketEntity(EntityTypes.PIG, viewers, modeledEntity.getBase().getLocation()); + return entity; + } + + public void runEntityTask() { + entityTask = new EntityTaskRunnable(plugin, this); + Bukkit.getAsyncScheduler().runAtFixedRate(plugin, entityTask, 0, 20, TimeUnit.MILLISECONDS); + } + + public PacketEntity getEntity() { + return entity; + } + + public Set getViewers() { + return viewers; + } + + public ModeledEntity getModeledEntity() { + return modeledEntity; + } + + public ActiveModel getActiveModel() { + return activeModel; + } + + public EntityTaskRunnable getEntityTask() { + return entityTask; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/player/PlayerManager.java b/src/main/java/re/imc/geysermodelengine/managers/player/PlayerManager.java new file mode 100644 index 0000000..c7a4d7a --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/player/PlayerManager.java @@ -0,0 +1,14 @@ +package re.imc.geysermodelengine.managers.player; + +import org.bukkit.entity.Player; + +import java.util.HashSet; + +public class PlayerManager { + + private final HashSet playerJoinedCache = new HashSet<>(); + + public HashSet getPlayerJoinedCache() { + return playerJoinedCache; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/server/ServerData.java b/src/main/java/re/imc/geysermodelengine/managers/server/ServerData.java new file mode 100644 index 0000000..5b6bbfc --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/server/ServerData.java @@ -0,0 +1,14 @@ +package re.imc.geysermodelengine.managers.server; + +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +import java.util.concurrent.ConcurrentHashMap; + +public class ServerData { + + private final ConcurrentHashMap activeRunnablesCache = new ConcurrentHashMap<>(); + + public ConcurrentHashMap getActiveRunnablesCache() { + return activeRunnablesCache; + } +} \ No newline at end of file diff --git a/src/main/java/re/imc/geysermodelengine/managers/server/ServerManager.java b/src/main/java/re/imc/geysermodelengine/managers/server/ServerManager.java new file mode 100644 index 0000000..a86d1b6 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/server/ServerManager.java @@ -0,0 +1,14 @@ +package re.imc.geysermodelengine.managers.server; + +public class ServerManager { + + private final ServerData serverData; + + public ServerManager() { + this.serverData = new ServerData(); + } + + public ServerData getServerData() { + return serverData; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/model/BedrockMountControl.java b/src/main/java/re/imc/geysermodelengine/model/BedrockMountControl.java deleted file mode 100644 index 83a11c2..0000000 --- a/src/main/java/re/imc/geysermodelengine/model/BedrockMountControl.java +++ /dev/null @@ -1,68 +0,0 @@ -package re.imc.geysermodelengine.model; - -import com.ticxo.modelengine.api.ModelEngineAPI; -import com.ticxo.modelengine.api.entity.BukkitEntity; -import com.ticxo.modelengine.api.model.ActiveModel; -import com.ticxo.modelengine.api.model.bone.type.Mount; -import com.ticxo.modelengine.api.mount.controller.MountController; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; -import org.geysermc.floodgate.api.FloodgateApi; -import re.imc.geysermodelengine.GeyserModelEngine; - -public class BedrockMountControl { - - public static void startTask() { - - new BukkitRunnable() { - @Override - public void run() { - for (Player player : Bukkit.getOnlinePlayers()) { - if (!FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId())) { - continue; - } - - float pitch = player.getLocation().getPitch(); - Pair seat = GeyserModelEngine.getInstance().getDrivers().get(player); - if (seat != null) { - if (pitch < -30) { - MountController controller = ModelEngineAPI.getMountPairManager() - .getController(player.getUniqueId()); - if (controller != null) { - MountController.MountInput input = controller.getInput(); - if (input != null) { - input.setJump(true); - controller.setInput(input); - } - } - } - if (pitch > 80) { - if (seat.getKey().getModeledEntity().getBase() instanceof BukkitEntity bukkitEntity) { - if (bukkitEntity.getOriginal().isOnGround()) { - return; - } - } - MountController controller = ModelEngineAPI.getMountPairManager() - .getController(player.getUniqueId()); - - if (controller != null) { - MountController.MountInput input = controller.getInput(); - if (input != null) { - input.setSneak(true); - controller.setInput(input); - } - } - } - - } - } - - } - }.runTaskTimerAsynchronously(GeyserModelEngine.getInstance(), 1, 1); - - - - } -} diff --git a/src/main/java/re/imc/geysermodelengine/model/EntityTask.java b/src/main/java/re/imc/geysermodelengine/model/EntityTask.java deleted file mode 100644 index d7539fa..0000000 --- a/src/main/java/re/imc/geysermodelengine/model/EntityTask.java +++ /dev/null @@ -1,406 +0,0 @@ -package re.imc.geysermodelengine.model; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.ticxo.modelengine.api.animation.BlueprintAnimation; -import com.ticxo.modelengine.api.animation.handler.AnimationHandler; -import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; -import com.ticxo.modelengine.api.model.ActiveModel; -import com.ticxo.modelengine.api.model.ModeledEntity; -import com.ticxo.modelengine.api.model.bone.ModelBone; -import com.ticxo.modelengine.api.model.render.DisplayRenderer; -import lombok.Getter; -import lombok.Setter; -import me.zimzaza4.geyserutils.spigot.api.EntityUtils; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.geysermc.floodgate.api.FloodgateApi; -import org.joml.Vector3f; -import org.joml.Vector3fc; -import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.packet.entity.PacketEntity; -import re.imc.geysermodelengine.util.BooleanPacker; - -import java.awt.*; -import java.lang.reflect.Method; -import java.util.*; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import static re.imc.geysermodelengine.model.ModelEntity.ENTITIES; -import static re.imc.geysermodelengine.model.ModelEntity.MODEL_ENTITIES; - -@Getter -@Setter -public class EntityTask { - public static final Method GET_SCALE; - - static { - try { - GET_SCALE = ActiveModel.class.getMethod("getScale"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - ModelEntity model; - - int tick = 0; - int syncTick = 0; - - boolean removed = false; - - float lastScale = -1.0f; - Color lastColor = null; - Map lastIntSet = new ConcurrentHashMap<>(); - Cache lastPlayedAnim = CacheBuilder.newBuilder() - .expireAfterWrite(30, TimeUnit.MILLISECONDS).build(); - - private ScheduledFuture scheduledFuture; - - public EntityTask(ModelEntity model) { - this.model = model; - } - public void runAsync() { - PacketEntity entity = model.getEntity(); - if (entity.isDead()) { - return; - } - - PacketEntity packetEntity = model.getEntity(); - // packetEntity.setHeadYaw((float) Math.toDegrees(model.getModeledEntity().getYHeadRot())); - // packetEntity.setHeadPitch((float) Math.toDegrees(model.getModeledEntity().getXHeadRot())); - model.teleportToModel(); - - Set viewers = model.getViewers(); - ActiveModel activeModel = model.getActiveModel(); - ModeledEntity modeledEntity = model.getModeledEntity(); - if (activeModel.isDestroyed() || activeModel.isRemoved()) { - removed = true; - entity.remove(); - - ENTITIES.remove(modeledEntity.getBase().getEntityId()); - MODEL_ENTITIES.remove(entity.getEntityId()); - cancel(); - return; - } - - - if (tick % 5 == 0) { - if (tick % 40 == 0) { - for (Player viewer : Set.copyOf(viewers)) { - if (!canSee(viewer, model.getEntity())) { - viewers.remove(viewer); - } - } - } - } - - tick ++; - if (tick > 400) { - tick = 0; - sendHitBoxToAll(); - } - - // Optional player = viewers.stream().findAny(); - // if (player.isEmpty()) return - - if (viewers.isEmpty()) { - return; - } - // updateEntityProperties(viewers, false); - - // do not actually use this, atleast bundle these up ;( - sendScale(viewers, false); - sendColor(viewers, false); - - - } - - public void checkViewers(Set viewers) { - for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { - if (FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) { - - if (canSee(onlinePlayer, model.getEntity())) { - - if (!viewers.contains(onlinePlayer)) { - sendSpawnPacket(onlinePlayer); - viewers.add(onlinePlayer); - } - } else { - if (viewers.contains(onlinePlayer)) { - model.getEntity().sendEntityDestroyPacket(Collections.singletonList(onlinePlayer)); - viewers.remove(onlinePlayer); - } - } - } - } - - } - - private void sendSpawnPacket(Player onlinePlayer) { - EntityTask task = model.getTask(); - boolean firstJoined = !GeyserModelEngine.getInstance().getJoinedPlayers().contains(onlinePlayer); - - if (firstJoined) { - task.sendEntityData(onlinePlayer, GeyserModelEngine.getInstance().getJoinSendDelay() / 50); - } else { - task.sendEntityData(onlinePlayer, 5); - } - } - - public void sendEntityData(Player player, int delay) { - EntityUtils.setCustomEntity(player, model.getEntity().getEntityId(), "modelengine:" + model.getActiveModel().getBlueprint().getName().toLowerCase()); - GeyserModelEngine.getInstance().getScheduler().schedule(() -> { - model.getEntity().sendSpawnPacket(Collections.singletonList(player)); - GeyserModelEngine.getInstance().getScheduler().schedule(() -> { - sendHitBox(player); - sendScale(Collections.singleton(player), true); - sendColor(Collections.singleton(player), true); - updateEntityProperties(Collections.singleton(player), true); - }, 500, TimeUnit.MILLISECONDS); - }, delay * 50L, TimeUnit.MILLISECONDS); - } - - public void sendScale(Collection players, boolean firstSend) { - try { - if (players.isEmpty()) { - return; - } - Vector3fc scale = (Vector3fc) GET_SCALE.invoke(model.getActiveModel()); - - float average = (scale.x() + scale.y() + scale.z()) / 3; - - if (!firstSend) { - if (average == lastScale) return; - } - for (Player player : players) { - EntityUtils.sendCustomScale(player, model.getEntity().getEntityId(), average); - } - lastScale = average; - } catch (Throwable t) { - // ignore - } - } - - public void sendColor(Collection players, boolean firstSend) { - if (players.isEmpty()) return; - - Color color = new Color(model.getActiveModel().getDefaultTint().asARGB()); - if (model.getActiveModel().isMarkedHurt()) { - color = new Color(model.getActiveModel().getDamageTint().asARGB()); - } - if (firstSend) { - if (color.equals(lastColor)) return; - } - for (Player player : players) { - EntityUtils.sendCustomColor(player, model.getEntity().getEntityId(), color); - } - lastColor = color; - } - - - public void updateEntityProperties(Collection players, boolean firstSend, String... forceAnims) { - int entity = model.getEntity().getEntityId(); - Set forceAnimSet = Set.of(forceAnims); - - Map boneUpdates = new HashMap<>(); - Map animUpdates = new HashMap<>(); - Set anims = new HashSet<>(); - // if (GeyserModelEngine.getInstance().getEnablePartVisibilityModels().contains(model.getActiveModel().getBlueprint().getName())) { - - model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> { - processBone(bone, boneUpdates); - }); - // } - - - AnimationHandler handler = model.getActiveModel().getAnimationHandler(); - Set priority = model.getActiveModel().getBlueprint().getAnimationDescendingPriority(); - for (String animId : priority) { - if (handler.isPlayingAnimation(animId)) { - BlueprintAnimation anim = model.getActiveModel().getBlueprint().getAnimations().get(animId); - - anims.add(animId); - if (anim.isOverride() && anim.getLoopMode() == BlueprintAnimation.LoopMode.ONCE) { - break; - } - } - } - - for (String id : priority) { - if (anims.contains(id)) { - animUpdates.put(id, true); - } else { - animUpdates.put(id, false); - } - } - - Set lastPlayed = new HashSet<>(lastPlayedAnim.asMap().keySet()); - - for (Map.Entry anim : animUpdates.entrySet()) { - if (anim.getValue()) { - lastPlayedAnim.put(anim.getKey(), true); - } - } - - for (String anim : lastPlayed) { - animUpdates.put(anim, true); - } - - - if (boneUpdates.isEmpty() && animUpdates.isEmpty()) return; - - Map intUpdates = new HashMap<>(); - int i = 0; - for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) { - intUpdates.put("modelengine:bone" + i, integer); - i++; - } - i = 0; - for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) { - intUpdates.put("modelengine:anim" + i, integer); - i++; - } - if (!firstSend) { - if (intUpdates.equals(lastIntSet)) { - return; - } else { - lastIntSet.clear(); - lastIntSet.putAll(intUpdates); - - } - } - - // System.out.println("AN: " + animUpdates.size() + ", BO:" + boneUpdates.size()); - if (GeyserModelEngine.getInstance().isDebug()) { - GeyserModelEngine.getInstance().getLogger().info(animUpdates.toString()); - } - - - List list = new ArrayList<>(boneUpdates.keySet()); - Collections.sort(list); - - for (Player player : players) { - EntityUtils.sendIntProperties(player, entity, intUpdates); - } - } - - private void processBone(BlueprintBone bone, Map map) { - String name = unstripName(bone).toLowerCase(); - if (name.equals("hitbox") || - name.equals("shadow") || - name.equals("mount") || - name.startsWith("p_") || - name.startsWith("b_") || - name.startsWith("ob_")) { - return; - } - for (BlueprintBone blueprintBone : bone.getChildren().values()) { - processBone(blueprintBone, map); - } - ModelBone activeBone = model.getActiveModel().getBones().get(bone.getName()); - - boolean visible = false; - if (activeBone != null) { - visible = activeBone.isVisible(); - } - map.put(name, visible); - } - private String unstripName(BlueprintBone bone) { - String name = bone.getName(); - if (bone.getBehaviors().get("head") != null) { - if (!bone.getBehaviors().get("head").isEmpty()) return "hi_" + name; - return "h_" + name; - } - - return name; - } - - public void sendHitBoxToAll() { - for (Player viewer : model.getViewers()) { - EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.01f, 0.01f); - } - - } - - public void sendHitBox(Player viewer) { - float w = 0; - - if (model.getActiveModel().isShadowVisible()) { - if (model.getActiveModel().getModelRenderer() instanceof DisplayRenderer displayRenderer) { - // w = displayRenderer.getHitbox().getShadowRadius().get(); - } - } - EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.02f, w); - - } - - public boolean hasAnimation(String animation) { - ActiveModel activeModel = model.getActiveModel(); - BlueprintAnimation animationProperty = activeModel.getBlueprint().getAnimations().get(animation); - return !(animationProperty == null); - } - - - private boolean canSee(Player player, PacketEntity entity) { - if (!player.isOnline()) { - return false; - } - if (!GeyserModelEngine.getInstance().getJoinedPlayers().contains(player)) { - return false; - } - - Location playerLocation = player.getLocation().clone(); - Location entityLocation = entity.getLocation().clone(); - playerLocation.setY(0); - entityLocation.setY(0); - if (playerLocation.getWorld() != entityLocation.getWorld()) { - return false; - } - if (playerLocation.distanceSquared(entityLocation) > player.getSendViewDistance() * player.getSendViewDistance() * 48) { - return false; - } - return true; - /* - if (entity.getLocation().getChunk() == player.getChunk()) { - return true; - } - if (entity.getLocation().getWorld() != player.getWorld()) { - return false; - } - if (player.getLocation().distanceSquared(entity.getLocation()) > player.getSimulationDistance() * player.getSimulationDistance() * 256) { - return false; - } - if (player.getLocation().distance(entity.getLocation()) > model.getActiveModel().getModeledEntity().getBase().getRenderRadius()) { - return false; - } - return true; - */ - } - - public void cancel() { - // syncTask.cancel(); - scheduledFuture.cancel(true); - } - - public void run(GeyserModelEngine instance) { - - sendHitBoxToAll(); - - Runnable asyncTask = () -> { - try { - checkViewers(model.getViewers()); - runAsync(); - } catch (Throwable t) { - - } - }; - scheduledFuture = GeyserModelEngine.getInstance().getScheduler().scheduleAtFixedRate(asyncTask, 0, 20, TimeUnit.MILLISECONDS); - - //asyncTask.runTaskTimerAsynchronously(instance, 0, 0); - } -} diff --git a/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java b/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java deleted file mode 100644 index 0bb73fe..0000000 --- a/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java +++ /dev/null @@ -1,70 +0,0 @@ -package re.imc.geysermodelengine.model; - -import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.google.common.collect.Sets; -import com.ticxo.modelengine.api.model.ActiveModel; -import com.ticxo.modelengine.api.model.ModeledEntity; -import lombok.Getter; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.packet.entity.PacketEntity; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -@Getter -public class ModelEntity { - - public static Map> ENTITIES = new ConcurrentHashMap<>(); - - public static Map MODEL_ENTITIES = new ConcurrentHashMap<>(); - - private PacketEntity entity; - - private final Set viewers = Sets.newConcurrentHashSet(); - - private final ModeledEntity modeledEntity; - - private final ActiveModel activeModel; - - private EntityTask task; - - private ModelEntity(ModeledEntity modeledEntity, ActiveModel model) { - this.modeledEntity = modeledEntity; - this.activeModel = model; - this.entity = spawnEntity(); - runEntityTask(); - } - - public void teleportToModel() { - Location location = modeledEntity.getBase().getLocation(); - entity.teleport(location); - } - public static ModelEntity create(ModeledEntity entity, ActiveModel model) { - ModelEntity modelEntity = new ModelEntity(entity, model); - int id = entity.getBase().getEntityId(); - Map map = ENTITIES.computeIfAbsent(id, k -> new HashMap<>()); - for (Map.Entry entry : map.entrySet()) { - if (entry.getKey() != model && entry.getKey().getBlueprint().getName().equals(model.getBlueprint().getName())) { - return null; - } - } - map.put(model, modelEntity); - return modelEntity; - } - - public PacketEntity spawnEntity() { - entity = new PacketEntity(EntityTypes.PIG, viewers, modeledEntity.getBase().getLocation()); - return entity; - } - - public void runEntityTask() { - task = new EntityTask(this); - task.run(GeyserModelEngine.getInstance()); - } - - -} diff --git a/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java index bfb14c6..f3cf64e 100644 --- a/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java +++ b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java @@ -27,14 +27,6 @@ import java.util.concurrent.ThreadLocalRandom; @Setter public class PacketEntity { - public PacketEntity(EntityType type, Set viewers, Location location) { - this.id = ThreadLocalRandom.current().nextInt(300000000, 400000000); - this.uuid = UUID.randomUUID(); - this.type = type; - this.viewers = viewers; - this.location = location; - } - private int id; private UUID uuid; private EntityType type; @@ -44,6 +36,15 @@ public class PacketEntity { private float headPitch; private boolean removed = false; + + public PacketEntity(EntityType type, Set viewers, Location location) { + this.id = ThreadLocalRandom.current().nextInt(300000000, 400000000); + this.uuid = UUID.randomUUID(); + this.type = type; + this.viewers = viewers; + this.location = location; + } + public @NotNull Location getLocation() { return location; } @@ -51,10 +52,9 @@ public class PacketEntity { public boolean teleport(@NotNull Location location) { boolean sent = this.location.getWorld() != location.getWorld() || this.location.distanceSquared(location) > 0.000001; this.location = location.clone(); - if (sent) { - sendLocationPacket(viewers); - // sendHeadRotation(viewers); // TODO - } + + if (sent) sendLocationPacket(viewers); + return true; } @@ -73,8 +73,6 @@ public class PacketEntity { } public void sendSpawnPacket(Collection players) { - // EntitySpawnPacket packet = new EntitySpawnPacket(id, uuid, type, location); - // EntityMetadataPacket metadataPacket = new EntityMetadataPacket(id); WrapperPlayServerSpawnEntity spawnEntity = new WrapperPlayServerSpawnEntity(id, uuid, type, SpigotConversionUtil.fromBukkitLocation(location), location.getYaw(), 0, null); players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, spawnEntity)); } @@ -83,13 +81,14 @@ public class PacketEntity { PacketWrapper packet; EntityPositionData data = new EntityPositionData(SpigotConversionUtil.fromBukkitLocation(location).getPosition(), Vector3d.zero(), location.getYaw(), location.getPitch()); + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) { packet = new WrapperPlayServerEntityPositionSync(id, data, false); } else { packet = new WrapperPlayServerEntityTeleport(id, data, RelativeFlag.NONE,false); } - players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet)); + players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet)); } public void sendHeadRotation(Collection players) { diff --git a/src/main/java/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.java b/src/main/java/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.java new file mode 100644 index 0000000..ad1f9a7 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/runnables/BedrockMountControlRunnable.java @@ -0,0 +1,66 @@ +package re.imc.geysermodelengine.runnables; + +import com.ticxo.modelengine.api.ModelEngineAPI; +import com.ticxo.modelengine.api.entity.BukkitEntity; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.bone.type.Mount; +import com.ticxo.modelengine.api.mount.controller.MountController; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.geysermc.floodgate.api.FloodgateApi; +import re.imc.geysermodelengine.GeyserModelEngine; + +import java.util.function.Consumer; + +public class BedrockMountControlRunnable implements Consumer { + + private final GeyserModelEngine plugin; + + public BedrockMountControlRunnable(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + @Override + public void accept(ScheduledTask scheduledTask) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (!FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId())) continue; + + float pitch = player.getLocation().getPitch(); + Pair seat = plugin.getBedrockMountControlManager().getDriversCache().get(player); + + if (seat == null) continue; + + if (pitch < -30) { + MountController controller = ModelEngineAPI.getMountPairManager() + .getController(player.getUniqueId()); + if (controller != null) { + MountController.MountInput input = controller.getInput(); + if (input != null) { + input.setJump(true); + controller.setInput(input); + } + } + } + + if (pitch > 80) { + if (seat.getKey().getModeledEntity().getBase() instanceof BukkitEntity bukkitEntity) { + if (bukkitEntity.getOriginal().isOnGround()) { + return; + } + } + + MountController controller = ModelEngineAPI.getMountPairManager().getController(player.getUniqueId()); + + if (controller != null) { + MountController.MountInput input = controller.getInput(); + if (input != null) { + input.setSneak(true); + controller.setInput(input); + } + } + } + } + } +} diff --git a/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java b/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java new file mode 100644 index 0000000..bb31aa2 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java @@ -0,0 +1,258 @@ +package re.imc.geysermodelengine.runnables; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.ticxo.modelengine.api.animation.BlueprintAnimation; +import com.ticxo.modelengine.api.animation.handler.AnimationHandler; +import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.ModeledEntity; +import com.ticxo.modelengine.api.model.bone.ModelBone; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; +import re.imc.geysermodelengine.packet.entity.PacketEntity; +import re.imc.geysermodelengine.util.BooleanPacker; + +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class EntityTaskRunnable implements Consumer { + + private final GeyserModelEngine plugin; + + private final ModelEntityData model; + + private int tick = 0; + private int syncTick = 0; + + private float lastScale = -1.0f; + private Color lastColor = null; + + private boolean removed = false; + + private final ConcurrentHashMap lastIntSet = new ConcurrentHashMap<>(); + private final Cache lastPlayedAnim = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MILLISECONDS).build(); + + private final BooleanPacker booleanPacker = new BooleanPacker(); + + public EntityTaskRunnable(GeyserModelEngine plugin, ModelEntityData model) { + this.plugin = plugin; + + this.model = model; + + plugin.getEntityTaskManager().sendHitBoxToAll(model); + } + + @Override + public void accept(ScheduledTask scheduledTask) { + plugin.getEntityTaskManager().checkViewers(model, model.getViewers()); + + PacketEntity entity = model.getEntity(); + if (entity.isDead()) return; + + model.teleportToModel(); + + Set viewers = model.getViewers(); + ActiveModel activeModel = model.getActiveModel(); + ModeledEntity modeledEntity = model.getModeledEntity(); + + if (activeModel.isDestroyed() || activeModel.isRemoved()) { + removed = true; + entity.remove(); + + plugin.getModelManager().getEntitiesCache().remove(modeledEntity.getBase().getEntityId()); + plugin.getModelManager().getModelEntitiesCache().remove(entity.getEntityId()); + scheduledTask.cancel(); + return; + } + + if (tick % 5 == 0) { + if (tick % 40 == 0) { + for (Player viewer : Set.copyOf(viewers)) { + if (!plugin.getEntityTaskManager().canSee(viewer, model.getEntity())) { + viewers.remove(viewer); + } + } + } + } + + tick ++; + if (tick > 400) { + tick = 0; + plugin.getEntityTaskManager().sendHitBoxToAll(model); + } + + if (viewers.isEmpty()) return; + + plugin.getEntityTaskManager().sendScale(model, viewers, lastScale, false); + plugin.getEntityTaskManager().sendColor(model, viewers, lastColor, false); + } + + public void sendEntityData(ModelEntityData model, Player player, int delay) { + EntityUtils.setCustomEntity(player, model.getEntity().getEntityId(), "modelengine:" + model.getActiveModel().getBlueprint().getName().toLowerCase()); + + Bukkit.getAsyncScheduler().runDelayed(plugin, scheduledTask -> { + model.getEntity().sendSpawnPacket(Collections.singletonList(player)); + + Bukkit.getAsyncScheduler().runDelayed(plugin, scheduledTask1 -> { + plugin.getEntityTaskManager().sendHitBox(model, player); + plugin.getEntityTaskManager().sendScale(model, Collections.singleton(player), lastScale, true); + plugin.getEntityTaskManager().sendColor(model, Collections.singleton(player), lastColor, true); + + updateEntityProperties(model, Collections.singleton(player), true); + }, 500, TimeUnit.MILLISECONDS); + }, delay * 50L, TimeUnit.MILLISECONDS); + } + + public void updateEntityProperties(ModelEntityData model, Collection players, boolean firstSend, String... forceAnims) { + int entity = model.getEntity().getEntityId(); + Set forceAnimSet = Set.of(forceAnims); + + Map boneUpdates = new HashMap<>(); + Map animUpdates = new HashMap<>(); + Set anims = new HashSet<>(); + + model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> processBone(model, bone, boneUpdates)); + + AnimationHandler handler = model.getActiveModel().getAnimationHandler(); + Set priority = model.getActiveModel().getBlueprint().getAnimationDescendingPriority(); + for (String animId : priority) { + if (handler.isPlayingAnimation(animId)) { + BlueprintAnimation anim = model.getActiveModel().getBlueprint().getAnimations().get(animId); + + anims.add(animId); + if (anim.isOverride() && anim.getLoopMode() == BlueprintAnimation.LoopMode.ONCE) { + break; + } + } + } + + for (String id : priority) { + if (anims.contains(id)) { + animUpdates.put(id, true); + } else { + animUpdates.put(id, false); + } + } + + Set lastPlayed = new HashSet<>(lastPlayedAnim.asMap().keySet()); + + for (Map.Entry anim : animUpdates.entrySet()) { + if (anim.getValue()) { + lastPlayedAnim.put(anim.getKey(), true); + } + } + + for (String anim : lastPlayed) animUpdates.put(anim, true); + + if (boneUpdates.isEmpty() && animUpdates.isEmpty()) return; + + Map intUpdates = new HashMap<>(); + int i = 0; + for (Integer integer : booleanPacker.mapBooleansToInts(boneUpdates)) { + intUpdates.put("modelengine:bone" + i, integer); + i++; + } + + i = 0; + for (Integer integer : booleanPacker.mapBooleansToInts(animUpdates)) { + intUpdates.put("modelengine:anim" + i, integer); + i++; + } + + if (!firstSend) { + if (intUpdates.equals(lastIntSet)) { + return; + } else { + lastIntSet.clear(); + lastIntSet.putAll(intUpdates); + } + } + + if (plugin.getConfigManager().getConfig().getBoolean("debug")) plugin.getLogger().info(animUpdates.toString()); + + List list = new ArrayList<>(boneUpdates.keySet()); + Collections.sort(list); + + for (Player player : players) { + EntityUtils.sendIntProperties(player, entity, intUpdates); + } + } + + private void processBone(ModelEntityData model, BlueprintBone bone, Map map) { + String name = plugin.getEntityTaskManager().unstripName(bone).toLowerCase(); + if (name.equals("hitbox") || + name.equals("shadow") || + name.equals("mount") || + name.startsWith("p_") || + name.startsWith("b_") || + name.startsWith("ob_")) { + return; + } + + for (BlueprintBone blueprintBone : bone.getChildren().values()) processBone(model, blueprintBone, map); + + ModelBone activeBone = model.getActiveModel().getBones().get(bone.getName()); + + boolean visible = false; + if (activeBone != null) visible = activeBone.isVisible(); + + map.put(name, visible); + } + + public void setTick(int tick) { + this.tick = tick; + } + + public void setSyncTick(int syncTick) { + this.syncTick = syncTick; + } + + public void setRemoved(boolean removed) { + this.removed = removed; + } + + public void setLastScale(float lastScale) { + this.lastScale = lastScale; + } + + public int getTick() { + return tick; + } + + public int getSyncTick() { + return syncTick; + } + + public void setLastColor(Color lastColor) { + this.lastColor = lastColor; + } + + public float getLastScale() { + return lastScale; + } + + public Color getLastColor() { + return lastColor; + } + + public boolean isRemoved() { + return removed; + } + + public ConcurrentHashMap getLastIntSet() { + return lastIntSet; + } + + public Cache getLastPlayedAnim() { + return lastPlayedAnim; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java b/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java new file mode 100644 index 0000000..015682b --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java @@ -0,0 +1,29 @@ +package re.imc.geysermodelengine.runnables; + +import com.ticxo.modelengine.api.model.ActiveModel; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.data.ModelEntityData; + +import java.util.Map; +import java.util.function.Consumer; + +public class UpdateTaskRunnable implements Consumer { + + private final GeyserModelEngine plugin; + + public UpdateTaskRunnable(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + @Override + public void accept(ScheduledTask scheduledTask) { + try { + for (Map models : plugin.getModelManager().getEntitiesCache().values()) { + models.values().forEach(model -> model.getEntityTask().updateEntityProperties(model, model.getViewers(), false)); + } + } catch (Throwable err) { + throw new RuntimeException(err); + } + } +} diff --git a/src/main/java/re/imc/geysermodelengine/util/BooleanPacker.java b/src/main/java/re/imc/geysermodelengine/util/BooleanPacker.java index 7b75956..5692a9d 100644 --- a/src/main/java/re/imc/geysermodelengine/util/BooleanPacker.java +++ b/src/main/java/re/imc/geysermodelengine/util/BooleanPacker.java @@ -6,25 +6,30 @@ import java.util.List; import java.util.Map; public class BooleanPacker { - public static final int MAX_BOOLEANS = 24; - public static int booleansToInt(List booleans) { + private final int MAX_BOOLEANS = 24; + + public int booleansToInt(List booleans) { int result = 0; int i = 1; + for (boolean b : booleans) { if (b) { result += i; } i *= 2; } + return result; } - public static int mapBooleansToInt(Map booleanMap) { + public int mapBooleansToInt(Map booleanMap) { int result = 0; int i = 1; + List keys = new ArrayList<>(booleanMap.keySet()); Collections.sort(keys); + for (String key : keys) { if (booleanMap.get(key)) { result += i; @@ -34,11 +39,12 @@ public class BooleanPacker { return result; } - public static List booleansToInts(List booleans) { + public List booleansToInts(List booleans) { List results = new ArrayList<>(); int result = 0; int i = 1; int i1 = 1; + for (boolean b : booleans) { if (b) { result += i; @@ -56,15 +62,15 @@ public class BooleanPacker { return results; } - public static List mapBooleansToInts(Map booleanMap) { + public List mapBooleansToInts(Map booleanMap) { List keys = new ArrayList<>(booleanMap.keySet()); List booleans = new ArrayList<>(); + Collections.sort(keys); + for (String key : keys) { booleans.add(booleanMap.get(key)); } return booleansToInts(booleans); } - - } diff --git a/src/main/java/re/imc/geysermodelengine/util/ColourUtils.java b/src/main/java/re/imc/geysermodelengine/util/ColourUtils.java new file mode 100644 index 0000000..5f53f7a --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/util/ColourUtils.java @@ -0,0 +1,29 @@ +package re.imc.geysermodelengine.util; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.jetbrains.annotations.NotNull; + +public class ColourUtils { + + private final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public @NotNull Component miniFormat(String message) { + return miniMessage.deserialize(message).decoration(TextDecoration.ITALIC, false); + } + + public @NotNull Component miniFormat(String message, TagResolver tagResolver) { + return miniMessage.deserialize(message, tagResolver).decoration(TextDecoration.ITALIC, false); + } + + public String stripColour(Component component) { + return PlainTextComponentSerializer.plainText().serialize(component); + } + + public MiniMessage getMiniMessage() { + return miniMessage; + } +} diff --git a/src/main/resources/Lang/messages.yml b/src/main/resources/Lang/messages.yml new file mode 100644 index 0000000..fdc999a --- /dev/null +++ b/src/main/resources/Lang/messages.yml @@ -0,0 +1,4 @@ + +commands: + reload: + successfully-reloaded: "<#55FF55>GeyserModelEngine configuration reloaded!" \ No newline at end of file diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml new file mode 100644 index 0000000..5a771d5 --- /dev/null +++ b/src/main/resources/paper-plugin.yml @@ -0,0 +1,18 @@ +main: re.imc.geysermodelengine.GeyserModelEngine +name: GeyserModelEngine +version: '1.0.0' +api-version: '1.21' + +authors: + - zimzaza4 + - willem.dev + - TheLividaProject + +dependencies: + server: + packetevents: + required: true + ModelEngine: + required: true + floodgate: + required: true \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml deleted file mode 100644 index 8f31d29..0000000 --- a/src/main/resources/plugin.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: GeyserModelEngine -version: '${project.version}' -main: re.imc.geysermodelengine.GeyserModelEngine -authors: - - zimzaza4 - - willem.dev -api-version: '1.19' -depend: - - ModelEngine - - floodgate -commands: - geysermodelengine: - usage: /geysermodelengine reload - permission: geysermodelengine.reload \ No newline at end of file