mirror of
https://github.com/GeyserExtensionists/GeyserModelEngine.git
synced 2025-12-19 15:09:18 +00:00
Merge branch 'main' of https://github.com/TheLividaProject/mc-GeyserModelEngine-plugin
# Conflicts: # pom.xml
This commit is contained in:
44
.gitignore
vendored
44
.gitignore
vendored
@@ -1,2 +1,42 @@
|
|||||||
# 项目排除路径
|
.gradle
|
||||||
/target/
|
build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
6
.idea/compiler.xml
generated
Normal file
6
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<bytecodeTargetLevel target="21" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
16
.idea/gradle.xml
generated
Normal file
16
.idea/gradle.xml
generated
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
|
<component name="GradleSettings">
|
||||||
|
<option name="linkedExternalProjectsSettings">
|
||||||
|
<GradleProjectSettings>
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="modules">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</GradleProjectSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
65
.idea/jarRepositories.xml
generated
Normal file
65
.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="codemc-snapshots" />
|
||||||
|
<option name="name" value="codemc-snapshots" />
|
||||||
|
<option name="url" value="https://repo.codemc.io/repository/maven-snapshots/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="opencollab-snapshot-repo" />
|
||||||
|
<option name="name" value="opencollab-snapshot-repo" />
|
||||||
|
<option name="url" value="https://repo.opencollab.dev/maven-snapshots/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="sonatype" />
|
||||||
|
<option name="name" value="sonatype" />
|
||||||
|
<option name="url" value="https://oss.sonatype.org/content/groups/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="opencollab-release-repo" />
|
||||||
|
<option name="name" value="opencollab-release-repo" />
|
||||||
|
<option name="url" value="https://repo.opencollab.dev/maven-releases/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="codemc-releases" />
|
||||||
|
<option name="name" value="codemc-releases" />
|
||||||
|
<option name="url" value="https://repo.codemc.io/repository/maven-releases/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="dmulloy2-repo" />
|
||||||
|
<option name="name" value="dmulloy2-repo" />
|
||||||
|
<option name="url" value="https://repo.dmulloy2.net/repository/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="papermc-repo" />
|
||||||
|
<option name="name" value="papermc-repo" />
|
||||||
|
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="nexus" />
|
||||||
|
<option name="name" value="Lumine Public" />
|
||||||
|
<option name="url" value="https://mvn.lumine.io/repository/maven-public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="md_5-public" />
|
||||||
|
<option name="name" value="md_5-public" />
|
||||||
|
<option name="url" value="https://repo.md-5.net/content/groups/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
5
.idea/misc.xml
generated
Normal file
5
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
139
.idea/workspace.xml
generated
Normal file
139
.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="ff2e9770-ec88-4715-adeb-b9dbda130e1a" name="Changes" comment="">
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="ExternalProjectsData">
|
||||||
|
<projectState path="$PROJECT_DIR$">
|
||||||
|
<ProjectState />
|
||||||
|
</projectState>
|
||||||
|
</component>
|
||||||
|
<component name="ExternalProjectsManager">
|
||||||
|
<system id="GRADLE">
|
||||||
|
<state>
|
||||||
|
<task path="$PROJECT_DIR$">
|
||||||
|
<activation />
|
||||||
|
</task>
|
||||||
|
<projects_view>
|
||||||
|
<tree_state>
|
||||||
|
<expand>
|
||||||
|
<path>
|
||||||
|
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||||
|
<item name="GeyserModelEngine" type="f1a62948:ProjectNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||||
|
<item name="GeyserModelEngine" type="f1a62948:ProjectNode" />
|
||||||
|
<item name="Tasks" type="e4a08cd1:TasksNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||||
|
<item name="GeyserModelEngine" type="f1a62948:ProjectNode" />
|
||||||
|
<item name="Tasks" type="e4a08cd1:TasksNode" />
|
||||||
|
<item name="build" type="c8890929:TasksNode$1" />
|
||||||
|
</path>
|
||||||
|
</expand>
|
||||||
|
<select />
|
||||||
|
</tree_state>
|
||||||
|
</projects_view>
|
||||||
|
</state>
|
||||||
|
</system>
|
||||||
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="Interface" />
|
||||||
|
<option value="Class" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="MavenRunner">
|
||||||
|
<option name="delegateBuildToMaven" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"associatedIndex": 8
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="2xedme8VKz03tyMoE1OuGEibnGo" />
|
||||||
|
<component name="ProjectLevelVcsManager">
|
||||||
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">{
|
||||||
|
"keyToString": {
|
||||||
|
"Gradle.GeyserModelEngine [jar].executor": "Run",
|
||||||
|
"Maven.GeyserModelEngine [install...].executor": "Run",
|
||||||
|
"Maven.GeyserModelEngine [install].executor": "Run",
|
||||||
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
|
"git-widget-placeholder": "main",
|
||||||
|
"last_opened_file_path": "D:/Coding/Forks/Minecraft/GeyserModelEngine",
|
||||||
|
"project.structure.last.edited": "Project",
|
||||||
|
"project.structure.proportion": "0.0",
|
||||||
|
"project.structure.side.proportion": "0.2",
|
||||||
|
"settings.editor.selected.configurable": "reference.settings.project.maven.runner"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="D:\Coding\Forks\Minecraft\GeyserModelEngine" />
|
||||||
|
</key>
|
||||||
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="D:\Coding\Forks\Minecraft\GeyserModelEngine\libs" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager">
|
||||||
|
<configuration name="GeyserModelEngine [jar]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="jar" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<recent_temporary>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="Gradle.GeyserModelEngine [jar]" />
|
||||||
|
</list>
|
||||||
|
</recent_temporary>
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="ff2e9770-ec88-4715-adeb-b9dbda130e1a" name="Changes" comment="" />
|
||||||
|
<created>1748302633990</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1748302633990</updated>
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="minecraft" name="Minecraft">
|
|
||||||
<configuration>
|
|
||||||
<autoDetectTypes>
|
|
||||||
<platformType>PAPER</platformType>
|
|
||||||
<platformType>ADVENTURE</platformType>
|
|
||||||
</autoDetectTypes>
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="McpModuleSettings">
|
|
||||||
<option name="srgType" value="SRG" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
56
build.gradle.kts
Normal file
56
build.gradle.kts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
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://central.sonatype.com/repository/maven-snapshots/")
|
||||||
|
|
||||||
|
maven("https://mvn.lumine.io/repository/maven-public/")
|
||||||
|
|
||||||
|
maven("https://repo.opencollab.dev/main/")
|
||||||
|
|
||||||
|
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.7-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
|
implementation("dev.jorel:commandapi-bukkit-shade-mojang-mapped:10.1.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.4-SNAPSHOT")
|
||||||
|
|
||||||
|
implementation("com.github.retrooper:packetevents-spigot:2.9.0-SNAPSHOT")
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -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
|
||||||
251
gradlew
vendored
Normal file
251
gradlew
vendored
Normal file
@@ -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" "$@"
|
||||||
94
gradlew.bat
vendored
Normal file
94
gradlew.bat
vendored
Normal file
@@ -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
|
||||||
Binary file not shown.
2
settings.gradle.kts
Normal file
2
settings.gradle.kts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = "GeyserModelEngine"
|
||||||
|
|
||||||
@@ -2,151 +2,98 @@ package re.imc.geysermodelengine;
|
|||||||
|
|
||||||
import com.github.retrooper.packetevents.PacketEvents;
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
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.ActiveModel;
|
||||||
import com.ticxo.modelengine.api.model.ModeledEntity;
|
import dev.jorel.commandapi.CommandAPI;
|
||||||
import com.ticxo.modelengine.api.model.bone.type.Mount;
|
import dev.jorel.commandapi.CommandAPIBukkitConfig;
|
||||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
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.Bukkit;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import re.imc.geysermodelengine.commands.ReloadCommand;
|
|
||||||
import re.imc.geysermodelengine.listener.ModelListener;
|
import re.imc.geysermodelengine.listener.ModelListener;
|
||||||
import re.imc.geysermodelengine.listener.MountPacketListener;
|
import re.imc.geysermodelengine.listener.MountPacketListener;
|
||||||
import re.imc.geysermodelengine.model.BedrockMountControl;
|
import re.imc.geysermodelengine.managers.ConfigManager;
|
||||||
import re.imc.geysermodelengine.model.ModelEntity;
|
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.model.data.ModelEntityData;
|
||||||
|
import re.imc.geysermodelengine.runnables.BedrockMountControlRunnable;
|
||||||
|
import re.imc.geysermodelengine.runnables.UpdateTaskRunnable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public final class GeyserModelEngine extends JavaPlugin {
|
public class GeyserModelEngine extends JavaPlugin {
|
||||||
|
|
||||||
@Getter
|
private ConfigManager configManager;
|
||||||
private static GeyserModelEngine instance;
|
|
||||||
|
|
||||||
@Getter
|
private CommandManager commandManager;
|
||||||
private static boolean alwaysSendSkin;
|
|
||||||
|
|
||||||
@Getter
|
private ModelManager modelManager;
|
||||||
private int sendDelay;
|
private EntityTaskManager entityTaskManager;
|
||||||
|
|
||||||
@Getter
|
|
||||||
private int viewDistance;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private Set<Player> joinedPlayers = new HashSet<>();
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private int joinSendDelay;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private long entityPositionUpdatePeriod;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private boolean debug;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private Map<Player, Pair<ActiveModel, Mount>> drivers = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private boolean initialized = false;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private List<String> enablePartVisibilityModels = new ArrayList<>();
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private ScheduledExecutorService scheduler;
|
|
||||||
private ScheduledFuture<?> updateTask;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||||
PacketEvents.getAPI().load();
|
PacketEvents.getAPI().load();
|
||||||
|
|
||||||
|
CommandAPI.onLoad(new CommandAPIBukkitConfig(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
PacketEvents.getAPI().init();
|
loadHooks();
|
||||||
PacketEvents.getAPI().getEventManager().registerListener(new MountPacketListener(), PacketListenerPriority.NORMAL);
|
loadManagers();
|
||||||
/*
|
loadRunnables();
|
||||||
scheduler.scheduleAtFixedRate(() -> {
|
|
||||||
try {
|
|
||||||
for (Map<ActiveModel, ModelEntity> models : ModelEntity.ENTITIES.values()) {
|
|
||||||
models.values().forEach(ModelEntity::teleportToModel);
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
}, 10, entityPositionUpdatePeriod, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
*/
|
PacketEvents.getAPI().getEventManager().registerListener(new MountPacketListener(this), PacketListenerPriority.NORMAL);
|
||||||
|
|
||||||
reload();
|
Bukkit.getPluginManager().registerEvents(new ModelListener(this), this);
|
||||||
getCommand("geysermodelengine").setExecutor(new ReloadCommand(this));
|
|
||||||
Bukkit.getPluginManager().registerEvents(new ModelListener(), this);
|
|
||||||
Bukkit.getScheduler()
|
|
||||||
.runTaskLater(GeyserModelEngine.getInstance(), () -> {
|
|
||||||
for (World world : Bukkit.getWorlds()) {
|
|
||||||
for (Entity entity : world.getEntities()) {
|
|
||||||
if (!ModelEntity.ENTITIES.containsKey(entity.getEntityId())) {
|
|
||||||
ModeledEntity modeledEntity = ModelEngineAPI.getModeledEntity(entity);
|
|
||||||
if (modeledEntity != null) {
|
|
||||||
Optional<ActiveModel> model = modeledEntity.getModels().values().stream().findFirst();
|
|
||||||
model.ifPresent(m -> ModelEntity.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<ActiveModel, ModelEntity> models : ModelEntity.ENTITIES.values()) {
|
|
||||||
models.values().forEach(model -> model.getTask().updateEntityProperties(model.getViewers(), false));
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
}, 10, entityPositionUpdatePeriod, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
PacketEvents.getAPI().terminate();
|
PacketEvents.getAPI().terminate();
|
||||||
for (Map<ActiveModel, ModelEntity> entities : ModelEntity.ENTITIES.values()) {
|
|
||||||
|
for (Map<ActiveModel, ModelEntityData> entities : modelManager.getEntitiesCache().values()) {
|
||||||
entities.forEach((model, modelEntity) -> {
|
entities.forEach((model, modelEntity) -> {
|
||||||
modelEntity.getEntity().remove();
|
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.commandManager = new CommandManager(this);
|
||||||
|
|
||||||
|
this.modelManager = new ModelManager(this);
|
||||||
|
this.entityTaskManager = new EntityTaskManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadRunnables() {
|
||||||
|
Bukkit.getAsyncScheduler().runAtFixedRate(this, new UpdateTaskRunnable(this), 10, configManager.getConfig().getLong("entity-position-update-period", 35), TimeUnit.MILLISECONDS);
|
||||||
|
Bukkit.getAsyncScheduler().runAtFixedRate(this, new BedrockMountControlRunnable(this), 1, 1, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigManager getConfigManager() {
|
||||||
|
return configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandManager getCommandManager() {
|
||||||
|
return commandManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelManager getModelManager() {
|
||||||
|
return modelManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityTaskManager getEntityTaskManager() {
|
||||||
|
return entityTaskManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
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")));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,126 +3,72 @@ package re.imc.geysermodelengine.listener;
|
|||||||
import com.ticxo.modelengine.api.events.AddModelEvent;
|
import com.ticxo.modelengine.api.events.AddModelEvent;
|
||||||
import com.ticxo.modelengine.api.events.ModelDismountEvent;
|
import com.ticxo.modelengine.api.events.ModelDismountEvent;
|
||||||
import com.ticxo.modelengine.api.events.ModelMountEvent;
|
import com.ticxo.modelengine.api.events.ModelMountEvent;
|
||||||
import com.ticxo.modelengine.api.events.RemoveModelEvent;
|
|
||||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
import re.imc.geysermodelengine.model.ModelEntity;
|
import re.imc.geysermodelengine.managers.model.data.ModelEntityData;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ModelListener implements Listener {
|
public class ModelListener implements Listener {
|
||||||
|
|
||||||
|
private final GeyserModelEngine plugin;
|
||||||
|
|
||||||
|
public ModelListener(GeyserModelEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onAddModel(AddModelEvent event) {
|
public void onAddModel(AddModelEvent event) {
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GeyserModelEngine.getInstance().isInitialized()) {
|
plugin.getModelManager().create(event.getTarget(), event.getModel());
|
||||||
return;
|
|
||||||
}
|
|
||||||
ModelEntity.create(event.getTarget(), event.getModel());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onRemoveModel(RemoveModelEvent event) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onModelMount(ModelMountEvent event) {
|
public void onModelMount(ModelMountEvent event) {
|
||||||
Map<ActiveModel, ModelEntity> map = ModelEntity.ENTITIES.get(event.getVehicle().getModeledEntity().getBase().getEntityId());
|
Map<ActiveModel, ModelEntityData> map = plugin.getModelManager().getEntitiesCache().get(event.getVehicle().getModeledEntity().getBase().getEntityId());
|
||||||
if (map == null) {
|
if (!event.isDriver()) return;
|
||||||
}
|
|
||||||
if (!event.isDriver()) {
|
ModelEntityData model = map.get(event.getVehicle());
|
||||||
return;
|
|
||||||
}
|
|
||||||
ModelEntity model = map.get(event.getVehicle());
|
|
||||||
|
|
||||||
if (model != null && event.getPassenger() instanceof Player player) {
|
if (model != null && event.getPassenger() instanceof Player player) {
|
||||||
GeyserModelEngine.getInstance().getDrivers().put(player, Pair.of(event.getVehicle(), event.getSeat()));
|
plugin.getModelManager().getDriversCache().put(player.getUniqueId(), Pair.of(event.getVehicle(), event.getSeat()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onModelDismount(ModelDismountEvent event) {
|
public void onModelDismount(ModelDismountEvent event) {
|
||||||
if (event.getPassenger() instanceof Player player) {
|
if (event.getPassenger() instanceof Player player) {
|
||||||
GeyserModelEngine.getInstance().getDrivers().remove(player);
|
plugin.getModelManager().getDriversCache().remove(player.getUniqueId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
|
||||||
public void onModelEntityHurt(EntityDamageEvent event) {
|
|
||||||
if (event.isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<ActiveModel, ModelEntity> model = ModelEntity.ENTITIES.get(event.getEntity().getEntityId());
|
|
||||||
if (model != null) {
|
|
||||||
for (Map.Entry<ActiveModel, ModelEntity> entry : model.entrySet()) {
|
|
||||||
if (!entry.getValue().getEntity().isDead()) {
|
|
||||||
//entry.getValue().getEntity().sendHurtPacket(entry.getValue().getViewers());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onModelAttack(EntityDamageByEntityEvent event) {
|
public void onWorldInit(WorldInitEvent event) {
|
||||||
ModelEntity model = ModelEntity.ENTITIES.get(event.getDamager().getEntityId());
|
World world = event.getWorld();
|
||||||
if (model != null) {
|
world.getEntities().forEach(entity -> plugin.getModelManager().processEntities(entity));
|
||||||
EntityTask task = model.getTask();
|
|
||||||
|
|
||||||
task.playAnimation("attack", 55);
|
|
||||||
}
|
|
||||||
}|
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
|
||||||
public void onAnimationPlay(AnimationPlayEvent event) {
|
|
||||||
Map<ActiveModel, ModelEntity> 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<ActiveModel, ModelEntity> 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().);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerLogin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> GeyserModelEngine.getInstance().getJoinedPlayers().add(event.getPlayer()), 10);
|
Player player = event.getPlayer();
|
||||||
|
plugin.getModelManager().getPlayerJoinedCache().add(player.getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> GeyserModelEngine.getInstance().getJoinedPlayers().remove(event.getPlayer()), 10);
|
Player player = event.getPlayer();
|
||||||
|
plugin.getModelManager().getPlayerJoinedCache().remove(player.getUniqueId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,31 @@ import com.ticxo.modelengine.api.ModelEngineAPI;
|
|||||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||||
import com.ticxo.modelengine.api.model.bone.type.Mount;
|
import com.ticxo.modelengine.api.model.bone.type.Mount;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
|
|
||||||
public class MountPacketListener implements PacketListener {
|
public class MountPacketListener implements PacketListener {
|
||||||
|
|
||||||
|
private final GeyserModelEngine plugin;
|
||||||
|
|
||||||
|
public MountPacketListener(GeyserModelEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketReceive(PacketReceiveEvent event) {
|
public void onPacketReceive(PacketReceiveEvent event) {
|
||||||
if (event.getPacketType() != PacketType.Play.Client.ENTITY_ACTION) {
|
if (event.getPacketType() != PacketType.Play.Client.ENTITY_ACTION) return;
|
||||||
return;
|
if (!FloodgateApi.getInstance().isFloodgatePlayer(event.getUser().getUUID())) return;
|
||||||
}
|
|
||||||
if (!FloodgateApi.getInstance().isFloodgatePlayer(event.getUser().getUUID())) {
|
Player player = event.getPlayer();
|
||||||
return;
|
|
||||||
}
|
|
||||||
WrapperPlayClientEntityAction action = new WrapperPlayClientEntityAction(event);
|
WrapperPlayClientEntityAction action = new WrapperPlayClientEntityAction(event);
|
||||||
Pair<ActiveModel, Mount> seat = GeyserModelEngine.getInstance().getDrivers().get(event.getPlayer());
|
Pair<ActiveModel, Mount> seat = plugin.getModelManager().getDriversCache().get(player.getUniqueId());
|
||||||
if (seat != null) {
|
|
||||||
if (action.getAction() == WrapperPlayClientEntityAction.Action.START_SNEAKING) {
|
if (seat == null) return;
|
||||||
|
if (action.getAction() != WrapperPlayClientEntityAction.Action.START_SNEAKING) return;
|
||||||
|
|
||||||
ModelEngineAPI.getMountPairManager().tryDismount(event.getPlayer());
|
ModelEngineAPI.getMountPairManager().tryDismount(event.getPlayer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
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() {
|
||||||
|
if (!plugin.getDataFolder().exists()) {
|
||||||
|
plugin.getDataFolder().mkdir();
|
||||||
|
plugin.saveResource("config.yml", false);
|
||||||
|
plugin.saveResource("Lang/messages.yml", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String, CommandManagers> 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<String, CommandManagers> getCommandManagersCache() {
|
||||||
|
return commandManagersCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<SubCommands> getCommands();
|
||||||
|
}
|
||||||
@@ -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<SubCommands> 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<SubCommands> getCommands() {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package re.imc.geysermodelengine.managers.commands.subcommands;
|
||||||
|
|
||||||
|
import dev.jorel.commandapi.CommandAPICommand;
|
||||||
|
|
||||||
|
public interface SubCommands {
|
||||||
|
CommandAPICommand onCommand();
|
||||||
|
}
|
||||||
@@ -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<Player> 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<Player> 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<Player> 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.getModelManager().getPlayerJoinedCache().contains(onlinePlayer.getUniqueId());
|
||||||
|
|
||||||
|
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.getModelManager().getPlayerJoinedCache().contains(player.getUniqueId())) 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package re.imc.geysermodelengine.managers.model;
|
||||||
|
|
||||||
|
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 org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
|
import re.imc.geysermodelengine.managers.model.data.ModelEntityData;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class ModelManager {
|
||||||
|
|
||||||
|
private final GeyserModelEngine plugin;
|
||||||
|
|
||||||
|
private final HashSet<UUID> playerJoinedCache = new HashSet<>();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Integer, Map<ActiveModel, ModelEntityData>> entitiesCache = new ConcurrentHashMap<>();
|
||||||
|
private final ConcurrentHashMap<Integer, ModelEntityData> modelEntitiesCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<UUID, Pair<ActiveModel, Mount>> driversCache = 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<ActiveModel, ModelEntityData> map = entitiesCache.computeIfAbsent(id, k -> new HashMap<>());
|
||||||
|
|
||||||
|
for (Map.Entry<ActiveModel, ModelEntityData> entry : map.entrySet()) {
|
||||||
|
if (entry.getKey() != model && entry.getKey().getBlueprint().getName().equals(model.getBlueprint().getName())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map.put(model, modelEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processEntities(Entity entity) {
|
||||||
|
if (entitiesCache.containsKey(entity.getEntityId())) return;
|
||||||
|
|
||||||
|
ModeledEntity modeledEntity = ModelEngineAPI.getModeledEntity(entity);
|
||||||
|
if (modeledEntity == null) return;
|
||||||
|
|
||||||
|
Optional<ActiveModel> model = modeledEntity.getModels().values().stream().findFirst();
|
||||||
|
model.ifPresent(m -> create(modeledEntity, m));
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<UUID> getPlayerJoinedCache() {
|
||||||
|
return playerJoinedCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<Integer, Map<ActiveModel, ModelEntityData>> getEntitiesCache() {
|
||||||
|
return entitiesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<Integer, ModelEntityData> getModelEntitiesCache() {
|
||||||
|
return modelEntitiesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<UUID, Pair<ActiveModel, Mount>> getDriversCache() {
|
||||||
|
return driversCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Player> 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<Player> getViewers() {
|
||||||
|
return viewers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeledEntity getModeledEntity() {
|
||||||
|
return modeledEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveModel getActiveModel() {
|
||||||
|
return activeModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityTaskRunnable getEntityTask() {
|
||||||
|
return entityTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ActiveModel, Mount> 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);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<String, Integer> lastIntSet = new ConcurrentHashMap<>();
|
|
||||||
Cache<String, Boolean> 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<Player> 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> 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<Player> 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<Player> 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<Player> 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<Player> players, boolean firstSend, String... forceAnims) {
|
|
||||||
int entity = model.getEntity().getEntityId();
|
|
||||||
Set<String> forceAnimSet = Set.of(forceAnims);
|
|
||||||
|
|
||||||
Map<String, Boolean> boneUpdates = new HashMap<>();
|
|
||||||
Map<String, Boolean> animUpdates = new HashMap<>();
|
|
||||||
Set<String> 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<String> 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<String> lastPlayed = new HashSet<>(lastPlayedAnim.asMap().keySet());
|
|
||||||
|
|
||||||
for (Map.Entry<String, Boolean> 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<String, Integer> 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<String> list = new ArrayList<>(boneUpdates.keySet());
|
|
||||||
Collections.sort(list);
|
|
||||||
|
|
||||||
for (Player player : players) {
|
|
||||||
EntityUtils.sendIntProperties(player, entity, intUpdates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processBone(BlueprintBone bone, Map<String, Boolean> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<Integer, Map<ActiveModel, ModelEntity>> ENTITIES = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public static Map<Integer, ModelEntity> MODEL_ENTITIES = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private PacketEntity entity;
|
|
||||||
|
|
||||||
private final Set<Player> 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<ActiveModel, ModelEntity> map = ENTITIES.computeIfAbsent(id, k -> new HashMap<>());
|
|
||||||
for (Map.Entry<ActiveModel, ModelEntity> 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -27,15 +27,6 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||||||
@Setter
|
@Setter
|
||||||
public class PacketEntity {
|
public class PacketEntity {
|
||||||
|
|
||||||
// public static final MinecraftVersion V1_20_5 = new MinecraftVersion("1.20.5");
|
|
||||||
public PacketEntity(EntityType type, Set<Player> 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 int id;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private EntityType type;
|
private EntityType type;
|
||||||
@@ -45,6 +36,15 @@ public class PacketEntity {
|
|||||||
private float headPitch;
|
private float headPitch;
|
||||||
|
|
||||||
private boolean removed = false;
|
private boolean removed = false;
|
||||||
|
|
||||||
|
public PacketEntity(EntityType type, Set<Player> 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() {
|
public @NotNull Location getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@@ -52,10 +52,9 @@ public class PacketEntity {
|
|||||||
public boolean teleport(@NotNull Location location) {
|
public boolean teleport(@NotNull Location location) {
|
||||||
boolean sent = this.location.getWorld() != location.getWorld() || this.location.distanceSquared(location) > 0.000001;
|
boolean sent = this.location.getWorld() != location.getWorld() || this.location.distanceSquared(location) > 0.000001;
|
||||||
this.location = location.clone();
|
this.location = location.clone();
|
||||||
if (sent) {
|
|
||||||
sendLocationPacket(viewers);
|
if (sent) sendLocationPacket(viewers);
|
||||||
// sendHeadRotation(viewers); // TODO
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +73,6 @@ public class PacketEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendSpawnPacket(Collection<Player> players) {
|
public void sendSpawnPacket(Collection<Player> 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);
|
WrapperPlayServerSpawnEntity spawnEntity = new WrapperPlayServerSpawnEntity(id, uuid, type, SpigotConversionUtil.fromBukkitLocation(location), location.getYaw(), 0, null);
|
||||||
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, spawnEntity));
|
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, spawnEntity));
|
||||||
}
|
}
|
||||||
@@ -84,13 +81,14 @@ public class PacketEntity {
|
|||||||
|
|
||||||
PacketWrapper<?> packet;
|
PacketWrapper<?> packet;
|
||||||
EntityPositionData data = new EntityPositionData(SpigotConversionUtil.fromBukkitLocation(location).getPosition(), Vector3d.zero(), location.getYaw(), location.getPitch());
|
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)) {
|
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||||
packet = new WrapperPlayServerEntityPositionSync(id, data, false);
|
packet = new WrapperPlayServerEntityPositionSync(id, data, false);
|
||||||
} else {
|
} else {
|
||||||
packet = new WrapperPlayServerEntityTeleport(id, data, RelativeFlag.NONE,false);
|
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<Player> players) {
|
public void sendHeadRotation(Collection<Player> players) {
|
||||||
@@ -106,84 +104,5 @@ public class PacketEntity {
|
|||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
public boolean teleport(@NotNull Location location) {
|
|
||||||
this.location = location.clone();
|
|
||||||
sendLocationPacket(viewers);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
removed = true;
|
|
||||||
sendEntityDestroyPacket(viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDead() {
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
return !removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendSpawnPacket(Collection<Player> players) {
|
|
||||||
EntitySpawnPacket packet = new EntitySpawnPacket(id, uuid, type, location);
|
|
||||||
// EntityMetadataPacket metadataPacket = new EntityMetadataPacket(id);
|
|
||||||
|
|
||||||
players.forEach(player -> {
|
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
|
||||||
});
|
|
||||||
sendAllEquipmentPacket(players);
|
|
||||||
// players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, metadataPacket.encode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendAllEquipmentPacket(Collection<Player> players) {
|
|
||||||
for (Map.Entry<EnumWrappers.ItemSlot, ItemStack> e : equipment.entrySet()) {
|
|
||||||
EntityEquipmentPacket packet = new EntityEquipmentPacket(id, e.getKey(), e.getValue());
|
|
||||||
|
|
||||||
players.forEach(player -> {
|
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendLocationPacket(Collection<Player> players) {
|
|
||||||
WrapperPacket packet = MinecraftVersion.v1_21_2.atOrAbove() ? new EntityPositionSyncPacket(id, location) : new EntityTeleportPacket(id, location);
|
|
||||||
players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendHurtPacket(Collection<Player> players) {
|
|
||||||
// 1.21 error
|
|
||||||
if (MinecraftVersion.getCurrentVersion().compareTo(V1_20_5) < 0) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EntityHurtPacket packet = new EntityHurtPacket(id);
|
|
||||||
players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
|
|
||||||
|
|
||||||
public void sendEntityDestroyPacket(Collection<Player> players) {
|
|
||||||
EntityDestroyPacket packet = new EntityDestroyPacket(id);
|
|
||||||
players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEntityId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSlot(EnumWrappers.ItemSlot slot, ItemStack itemStack) {
|
|
||||||
if (itemStack == null) {
|
|
||||||
itemStack = new ItemStack(Material.AIR);
|
|
||||||
}
|
|
||||||
equipment.put(slot, itemStack);
|
|
||||||
EntityEquipmentPacket packet = new EntityEquipmentPacket(id, slot, itemStack);
|
|
||||||
viewers.forEach(player -> {
|
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
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<ScheduledTask> {
|
||||||
|
|
||||||
|
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<ActiveModel, Mount> seat = plugin.getModelManager().getDriversCache().get(player.getUniqueId());
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ScheduledTask> {
|
||||||
|
|
||||||
|
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<String, Integer> lastIntSet = new ConcurrentHashMap<>();
|
||||||
|
private final Cache<String, Boolean> 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<Player> 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<Player> players, boolean firstSend, String... forceAnims) {
|
||||||
|
int entity = model.getEntity().getEntityId();
|
||||||
|
Set<String> forceAnimSet = Set.of(forceAnims);
|
||||||
|
|
||||||
|
Map<String, Boolean> boneUpdates = new HashMap<>();
|
||||||
|
Map<String, Boolean> animUpdates = new HashMap<>();
|
||||||
|
Set<String> anims = new HashSet<>();
|
||||||
|
|
||||||
|
model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> processBone(model, bone, boneUpdates));
|
||||||
|
|
||||||
|
AnimationHandler handler = model.getActiveModel().getAnimationHandler();
|
||||||
|
Set<String> 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<String> lastPlayed = new HashSet<>(lastPlayedAnim.asMap().keySet());
|
||||||
|
|
||||||
|
for (Map.Entry<String, Boolean> 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<String, Integer> 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<String> 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<String, Boolean> 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<String, Integer> getLastIntSet() {
|
||||||
|
return lastIntSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cache<String, Boolean> getLastPlayedAnim() {
|
||||||
|
return lastPlayedAnim;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ScheduledTask> {
|
||||||
|
|
||||||
|
private final GeyserModelEngine plugin;
|
||||||
|
|
||||||
|
public UpdateTaskRunnable(GeyserModelEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ScheduledTask scheduledTask) {
|
||||||
|
try {
|
||||||
|
for (Map<ActiveModel, ModelEntityData> models : plugin.getModelManager().getEntitiesCache().values()) {
|
||||||
|
models.values().forEach(model -> model.getEntityTask().updateEntityProperties(model, model.getViewers(), false));
|
||||||
|
}
|
||||||
|
} catch (Throwable err) {
|
||||||
|
throw new RuntimeException(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,25 +6,30 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BooleanPacker {
|
public class BooleanPacker {
|
||||||
public static final int MAX_BOOLEANS = 24;
|
|
||||||
|
|
||||||
public static int booleansToInt(List<Boolean> booleans) {
|
private final int MAX_BOOLEANS = 24;
|
||||||
|
|
||||||
|
public int booleansToInt(List<Boolean> booleans) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
for (boolean b : booleans) {
|
for (boolean b : booleans) {
|
||||||
if (b) {
|
if (b) {
|
||||||
result += i;
|
result += i;
|
||||||
}
|
}
|
||||||
i *= 2;
|
i *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int mapBooleansToInt(Map<String, Boolean> booleanMap) {
|
public int mapBooleansToInt(Map<String, Boolean> booleanMap) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
||||||
Collections.sort(keys);
|
Collections.sort(keys);
|
||||||
|
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
if (booleanMap.get(key)) {
|
if (booleanMap.get(key)) {
|
||||||
result += i;
|
result += i;
|
||||||
@@ -34,11 +39,12 @@ public class BooleanPacker {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Integer> booleansToInts(List<Boolean> booleans) {
|
public List<Integer> booleansToInts(List<Boolean> booleans) {
|
||||||
List<Integer> results = new ArrayList<>();
|
List<Integer> results = new ArrayList<>();
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
int i1 = 1;
|
int i1 = 1;
|
||||||
|
|
||||||
for (boolean b : booleans) {
|
for (boolean b : booleans) {
|
||||||
if (b) {
|
if (b) {
|
||||||
result += i;
|
result += i;
|
||||||
@@ -56,15 +62,15 @@ public class BooleanPacker {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Integer> mapBooleansToInts(Map<String, Boolean> booleanMap) {
|
public List<Integer> mapBooleansToInts(Map<String, Boolean> booleanMap) {
|
||||||
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
||||||
List<Boolean> booleans = new ArrayList<>();
|
List<Boolean> booleans = new ArrayList<>();
|
||||||
|
|
||||||
Collections.sort(keys);
|
Collections.sort(keys);
|
||||||
|
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
booleans.add(booleanMap.get(key));
|
booleans.add(booleanMap.get(key));
|
||||||
}
|
}
|
||||||
return booleansToInts(booleans);
|
return booleansToInts(booleans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/main/java/re/imc/geysermodelengine/util/ColourUtils.java
Normal file
29
src/main/java/re/imc/geysermodelengine/util/ColourUtils.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/main/resources/Lang/messages.yml
Normal file
4
src/main/resources/Lang/messages.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
commands:
|
||||||
|
reload:
|
||||||
|
successfully-reloaded: "<#55FF55>GeyserModelEngine configuration reloaded!"
|
||||||
22
src/main/resources/paper-plugin.yml
Normal file
22
src/main/resources/paper-plugin.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
main: re.imc.geysermodelengine.GeyserModelEngine
|
||||||
|
name: GeyserModelEngine
|
||||||
|
version: '1.0.0'
|
||||||
|
api-version: '1.21'
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- zimzaza4
|
||||||
|
- willem.dev
|
||||||
|
- TheLividaProject
|
||||||
|
|
||||||
|
load: STARTUP
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
server:
|
||||||
|
GeyserUtils:
|
||||||
|
required: true
|
||||||
|
packetevents:
|
||||||
|
required: true
|
||||||
|
ModelEngine:
|
||||||
|
required: true
|
||||||
|
floodgate:
|
||||||
|
required: true
|
||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user