├── .gitignore ├── LICENSE.md ├── README.md ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── kotlin │ ├── Dependency.kt │ └── Project.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── run ├── settings.gradle.kts ├── tap-api ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ ├── collection │ │ └── SortedList.kt │ │ ├── config │ │ ├── ConfigSupport.kt │ │ └── EnumSupport.kt │ │ ├── data │ │ ├── PersistentDataKey.kt │ │ ├── PersistentDataKeychain.kt │ │ └── PersistentDataSupport.kt │ │ ├── event │ │ ├── DefaultProvider.kt │ │ ├── EntityEventManager.kt │ │ ├── EntityHandlerList.kt │ │ ├── EntityProvider.kt │ │ ├── EventEntity.kt │ │ ├── EventEntityProvider.kt │ │ ├── EventTools.kt │ │ ├── HandlerStatement.kt │ │ ├── ListenerStatement.kt │ │ ├── RegisteredEntityHandler.kt │ │ ├── RegisteredEntityListener.kt │ │ └── TargetEntity.kt │ │ ├── fake │ │ ├── FakeEntity.kt │ │ ├── FakeEntityServer.kt │ │ ├── FakeProjectile.kt │ │ ├── FakeProjectileManager.kt │ │ ├── FakeSkinParts.kt │ │ └── FakeSupport.kt │ │ ├── hash │ │ └── LongHash.kt │ │ ├── item │ │ └── ItemSupport.kt │ │ ├── loader │ │ └── LibraryLoader.kt │ │ ├── math │ │ ├── LocationSupport.kt │ │ ├── MathSupport.kt │ │ ├── VectorSupport.kt │ │ └── WorldSupport.kt │ │ ├── mojangapi │ │ └── MojangAPI.kt │ │ ├── protocol │ │ ├── AnimationType.kt │ │ ├── PacketContainer.kt │ │ ├── PacketSupport.kt │ │ ├── PlayerInfoAction.kt │ │ └── PlayerInfoUpdateAction.kt │ │ ├── ref │ │ └── Weaky.kt │ │ ├── task │ │ ├── Ticker.kt │ │ └── TickerTask.kt │ │ ├── template │ │ ├── ComponentSupport.kt │ │ └── TemplateSupport.kt │ │ ├── trail │ │ └── TrailSupport.kt │ │ └── util │ │ ├── AlphanumComparator.kt │ │ ├── GameModeSupport.kt │ │ ├── GitHubSupport.kt │ │ └── VersionSupport.kt │ └── test │ └── kotlin │ └── io │ └── github │ └── monun │ └── tap │ └── mojangapi │ └── MojangAPITest.kt ├── tap-core ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── io │ └── github │ └── monun │ └── tap │ └── fake │ └── internal │ ├── FakeEntityImpl.kt │ ├── FakeEntityServerImpl.kt │ ├── FakeInternalImpl.kt │ └── FakeTracker.kt ├── tap-dongle ├── build.gradle.kts ├── v1.18.1 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_18_1 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.18.2 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_18_2 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.18 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_18 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.19.1 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_19_1 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.19.2 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_19_2 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.19.3 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_19_3 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.19.4 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_19_4 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.19 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_19 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt ├── v1.20.1 │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── v1_20_1 │ │ ├── fake │ │ ├── NMSEntityTypes.kt │ │ └── NMSFakeSupport.kt │ │ ├── item │ │ └── NMSItemSupport.kt │ │ └── protocol │ │ ├── NMSPacketContainer.kt │ │ └── NMSPacketSupport.kt └── v1.20 │ └── src │ └── main │ └── kotlin │ └── io │ └── github │ └── monun │ └── tap │ └── v1_20 │ ├── fake │ ├── NMSEntityTypes.kt │ └── NMSFakeSupport.kt │ ├── item │ └── NMSItemSupport.kt │ └── protocol │ ├── NMSPacketContainer.kt │ └── NMSPacketSupport.kt ├── tap-plugin ├── build.gradle.kts └── src │ └── main │ ├── kotlin │ └── io │ │ └── github │ │ └── monun │ │ └── tap │ │ └── plugin │ │ ├── TapPlugin.kt │ │ └── test │ │ ├── TapTest.kt │ │ ├── TestUnit.kt │ │ └── unit │ │ ├── complex │ │ └── TestFakeEntityPose.kt │ │ └── simple │ │ ├── TestConfigSupport.kt │ │ ├── TestNewVersionFetchSupport.kt │ │ └── TestPersistentDataSupport.kt │ └── resources │ ├── META-INF │ └── PLUGIN_LICENSE │ ├── bundle.yml │ └── clip.yml └── tap-publish └── build.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | .idea/ 3 | out/ 4 | 5 | # Gradle 6 | .gradle 7 | build/ 8 | 9 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 10 | !gradle-wrapper.jar 11 | !gradle-wrapper.properties 12 | 13 | # Debug server folder 14 | .server/ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tap 2 | 3 | [![Kotlin](https://img.shields.io/badge/java-17-ED8B00.svg?logo=java)](https://www.azul.com/) 4 | [![Kotlin](https://img.shields.io/badge/kotlin-1.8.22-585DEF.svg?logo=kotlin)](http://kotlinlang.org) 5 | [![Gradle](https://img.shields.io/badge/gradle-8.2.1-02303A.svg?logo=gradle)](https://gradle.org) 6 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.monun/tap-core)](https://search.maven.org/artifact/io.github.monun/tap-core) 7 | [![GitHub](https://img.shields.io/github/license/monun/tap)](https://www.gnu.org/licenses/gpl-3.0.html) 8 | [![Kotlin](https://img.shields.io/badge/youtube-각별-red.svg?logo=youtube)](https://www.youtube.com/channel/UCDrAR1OWC2MD4s0JLetN0MA) 9 | 10 | ### Paper 확장 라이브러리 11 | 12 | 컨텐츠 제작에 자주 사용하는 기능을 제공합니다. 13 | 14 | --- 15 | 16 | * #### Features 17 | * 개체 패킷 18 | * 가상 개체 19 | * 가상 발사체 20 | * 개체별 이벤트 리스너 21 | * YamlConfiguration을 이용한 문자열 템플릿 22 | * 추가적인 인벤토리 함수 23 | * GitHub를 통한 업데이트 24 | * Tick 기반 태스크 스케쥴러 (Ticker) 25 | * PersistentData API 접근성 개선 26 | 27 | * #### Supported minecraft versions 28 | * 1.18 29 | * 1.18.1 30 | * 1.18.2 31 | * 1.19 32 | * 1.19.1 33 | * 1.19.2 34 | * 1.19.3 35 | * 1.19.4 36 | * 1.20 37 | * 1.20.1 38 | 39 | --- 40 | 41 | ### Gradle `tap-api` 42 | 43 | ```kotlin 44 | repositories { 45 | mavenCentral() 46 | } 47 | ``` 48 | 49 | ```kotlin 50 | dependencies { 51 | implementation("io.github.monun:tap-api:") 52 | } 53 | ``` 54 | 55 | ### plugin.yml `tap-core` 56 | 57 | ```yaml 58 | name: ... 59 | version: ... 60 | main: ... 61 | libraries: 62 | - io.github.monun:tap-core: 63 | ``` 64 | 65 | #### !!주의!! 66 | 67 | * `Gradle`과 `plugin.yml`의 의존성 패키지가 다르므로 주의해주세요. 68 | * 모든 코드는 ShadowJar를 고려하여 작성되지 않았습니다. 69 | 70 | --- 71 | 72 | ### NOTE 73 | 74 | * 라이센스는 GPL-3.0이며 변경 혹은 삭제를 금합니다. 75 | 76 | --- 77 | 78 | ### Contributors 79 | 80 | * [**patrick-choe**](https://github.com/patrick-choe) 81 | * java 소스 코드 제거 (java -> kotlin) 82 | * mojang-mapping 빌드환경 구축 83 | * mavenCentral 배포 84 | * ProtocolLib 의존성 제거 (nms packet 직접 지원) 85 | * [**dolphin2410**](https://github.com/dolphin2410) 86 | * FakeFallingBlock 버그 수정 87 | * Version identifier 추가 88 | * 일부 코드 향상 89 | * FakeEntity에 Player 지원 90 | 91 | [![Jetbrains](https://i.ibb.co/fp0CyZ7/jetbrains.png)](https://jb.gg/OpenSource) 92 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | idea 3 | kotlin("jvm") version Dependency.Kotlin.Version 4 | kotlin("plugin.serialization") version Dependency.Kotlin.Version apply false 5 | id("org.jetbrains.dokka") version Dependency.Dokka.Version apply false 6 | } 7 | 8 | java { 9 | toolchain { 10 | languageVersion.set(JavaLanguageVersion.of(17)) 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | mavenCentral() 17 | } 18 | } 19 | 20 | subprojects { 21 | apply(plugin = "org.jetbrains.kotlin.jvm") 22 | apply(plugin = "org.jetbrains.kotlin.plugin.serialization") 23 | 24 | repositories { 25 | maven("https://papermc.io/repo/repository/maven-public/") 26 | } 27 | 28 | dependencies { 29 | compileOnly("io.papermc.paper:paper-api:${Dependency.Paper.Version}-R0.1-SNAPSHOT") 30 | 31 | implementation(kotlin("stdlib")) 32 | implementation(kotlin("reflect")) 33 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") 34 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.1") 35 | 36 | testImplementation("org.junit.jupiter:junit-jupiter:5.7.1") 37 | } 38 | 39 | tasks { 40 | test { 41 | useJUnitPlatform() 42 | } 43 | } 44 | } 45 | 46 | listOf("api", "core").forEach { projectName -> 47 | project(":${rootProject.name}-$projectName") { 48 | apply(plugin = "org.jetbrains.dokka") 49 | 50 | tasks { 51 | create("sourcesJar") { 52 | archiveClassifier.set("sources") 53 | from(sourceSets["main"].allSource) 54 | } 55 | 56 | create("dokkaJar") { 57 | archiveClassifier.set("javadoc") 58 | dependsOn("dokkaHtml") 59 | 60 | from("$buildDir/dokka/html/") { 61 | include("**") 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | idea { 69 | module { 70 | excludeDirs.add(file(".server")) 71 | excludeDirs.addAll(allprojects.map { it.buildDir }) 72 | excludeDirs.addAll(allprojects.map { it.file(".gradle") }) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/Dependency.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | object Dependency { 19 | object Kotlin { 20 | const val Version = "1.8.22" 21 | } 22 | 23 | object Dokka { 24 | const val Version = "1.8.20" 25 | } 26 | 27 | object Paper { 28 | const val Version = "1.18" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/Project.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import org.gradle.api.Project 19 | import org.gradle.jvm.tasks.Jar 20 | 21 | private fun Project.subproject(name: String) = project(":${rootProject.name}-$name") 22 | 23 | val Project.projectApi 24 | get() = subproject("api") 25 | 26 | val Project.projectCore 27 | get() = subproject("core") 28 | 29 | val Project.projectDongle 30 | get() = findProject(":${rootProject.name}-dongle") 31 | 32 | val Project.projectPlugin 33 | get() = subproject("plugin") 34 | 35 | private fun Project.coreTask(name: String) = projectCore.tasks.named(name, Jar::class.java) 36 | 37 | val Project.coreDevJar 38 | get() = coreTask("coreDevJar") 39 | 40 | val Project.coreReobfJar 41 | get() = coreTask("coreReobfJar") 42 | 43 | val Project.coreSourcesJar 44 | get() = coreTask("sourcesJar") -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | org.gradle.jvmargs=-Xmx4G 3 | group=io.github.monun 4 | version=4.9.8 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monun/tap/4a2afd8ae5198d4ff61e82fa0001682e00fd648d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | classifier="dev" 4 | [[ $1 == "reobf" ]] && classifier="reobf" 5 | [[ $1 == "clip" ]] && classifier="clip" 6 | 7 | ####################### Configuration Section ##################### 8 | 9 | # Use following variables as global-scope 10 | set -a 11 | 12 | ######################## Upstream Settings ######################### 13 | REPO_BASE_URL="https://raw.githubusercontent.com/monun/minecraft-server-launcher" 14 | REPO_BRANCH="master" 15 | 16 | REPO_ROOT="$REPO_BASE_URL/$REPO_BRANCH" 17 | REPO_DEPLOY="$REPO_ROOT/deploy" 18 | 19 | ########################## Configurations ########################## 20 | ## Server directory name 21 | DIR=".server" 22 | 23 | ## Server type (local path or type[vanilla, spigot, paper]-version[1.xx.x, unspecified]-build[latest, unspecified, xx]-[dev]) 24 | SERVER="paper-1.20.1-latest-$classifier" 25 | 26 | ## Server memory (GB) 27 | MEMORY=4 28 | 29 | ## When the server shuts down, use tar to back up. 30 | BACKUP=false 31 | 32 | ## The server will always restart. 33 | RESTART=false 34 | 35 | ################## Spigot or Paper Configurations ################## 36 | ## The maximum amount of players that the server will allow, this will bypass the max-players= value in server.properties file. 37 | PLAYERS=100 38 | 39 | ## This parameter allows you to manually define the plugins directory to use for the server. 40 | PLUGINS="plugins-$classifier" 41 | 42 | ## This parameter will put all worlds your server uses into a specific directory, it's useful if you have many folders inside in the main server directory. 43 | WORLDS="worlds" 44 | 45 | ## Server port, default value from server.properties (25565) 46 | PORT=-1 47 | 48 | ## jdwp port, Enable debug mode when 0 or higher (5005) 49 | DEBUG_PORT=5005 50 | 51 | # Preinstallation plugins (url) 52 | DEFAULT_PLUGINS=( 53 | 'https://github.com/monun/auto-reloader/releases/download/0.0.6/auto-reloader-0.0.6.jar' 54 | ) 55 | 56 | # Uncomment to enable OpenJ9 performance tuning for VMs 57 | # VIRTUALIZED=true 58 | 59 | # Use following variables as local-scope 60 | set +a 61 | 62 | ####################### End of Configuration ###################### 63 | 64 | # Setup target directory 65 | mkdir -p "$DIR" && cd "$DIR" || exit 66 | [[ ! -f ./startSetup ]] && wget -q -c --content-disposition -P . -N "$REPO_DEPLOY/startSetup" >/dev/null 67 | chmod +x ./startSetup 68 | ./startSetup "${DEFAULT_PLUGINS[@]}" 69 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "tap" 2 | 3 | val prefix = rootProject.name 4 | 5 | include("$prefix-api", "$prefix-core", "$prefix-plugin") 6 | 7 | val dongle = "$prefix-dongle" 8 | val dongleFile = file(dongle) 9 | if (dongleFile.exists()) { 10 | include(dongle) 11 | // load nms 12 | dongleFile.listFiles()?.filter { 13 | it.isDirectory && it.name.startsWith("v") 14 | }?.forEach { file -> 15 | include(":$dongle:${file.name}") 16 | } 17 | } 18 | 19 | val publish = "$prefix-publish" 20 | if (file(publish).exists()) include(publish) -------------------------------------------------------------------------------- /tap-api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") 3 | implementation("org.mariuszgromada.math:MathParser.org-mXparser:5.0.6") 4 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/collection/SortedList.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.collection 19 | 20 | import java.util.* 21 | 22 | @Suppress("unused") 23 | /** 24 | * 요소 추가삭제시 자동으로 정렬하는 리스트 25 | */ 26 | class SortedList : AbstractList, RandomAccess, Cloneable { 27 | private val list: ArrayList 28 | private val comparator: Comparator? 29 | 30 | constructor() { 31 | list = ArrayList() 32 | comparator = null 33 | } 34 | 35 | constructor(comparator: Comparator? = null) { 36 | list = ArrayList() 37 | this.comparator = comparator 38 | } 39 | 40 | constructor(initialCapacity: Int, comparator: Comparator? = null) { 41 | list = ArrayList(initialCapacity) 42 | this.comparator = comparator 43 | } 44 | 45 | constructor(elements: Collection, comparator: Comparator? = null) { 46 | list = ArrayList(elements) 47 | this.comparator = comparator 48 | sort() 49 | } 50 | 51 | override fun add(element: E): Boolean { 52 | sort() 53 | binaryAdd(element) 54 | return true 55 | } 56 | 57 | fun sort() { 58 | Collections.sort(list, comparator) 59 | } 60 | 61 | fun binaryAdd(element: E): Int { 62 | modCount++ 63 | val size = list.size 64 | if (size == 0) { 65 | list.add(element) 66 | return 0 67 | } 68 | var index = binarySearch(element) 69 | if (index < 0) index = -(index + 1) 70 | list.add(index, element) 71 | return index 72 | } 73 | 74 | fun binaryRemove(element: E): Boolean { 75 | val index = binarySearch(element) 76 | if (index >= 0) { 77 | list.removeAt(index) 78 | return true 79 | } 80 | return false 81 | } 82 | 83 | override fun addAll(elements: Collection): Boolean { 84 | list.ensureCapacity(elements.size) 85 | for (element in elements) add(element) 86 | return true 87 | } 88 | 89 | override fun clear() { 90 | list.clear() 91 | } 92 | 93 | override operator fun contains(element: E): Boolean { 94 | return list.contains(element) 95 | } 96 | 97 | override fun containsAll(elements: Collection): Boolean { 98 | return list.containsAll(elements) 99 | } 100 | 101 | override fun equals(other: Any?): Boolean { 102 | return other is SortedList<*> && list == other.list 103 | } 104 | 105 | private fun binarySearch(element: E): Int { 106 | return Collections.binarySearch(list, element, comparator) 107 | } 108 | 109 | override fun get(index: Int): E { 110 | return list[index] 111 | } 112 | 113 | override fun hashCode(): Int { 114 | return list.hashCode() 115 | } 116 | 117 | override fun indexOf(element: E): Int { 118 | return list.indexOf(element) 119 | } 120 | 121 | override fun isEmpty(): Boolean { 122 | return list.isEmpty() 123 | } 124 | 125 | override fun lastIndexOf(element: E): Int { 126 | return list.lastIndexOf(element) 127 | } 128 | 129 | override fun listIterator(index: Int): MutableListIterator { 130 | return object : MutableListIterator { 131 | private val iterator = list.listIterator(index) 132 | override fun add(element: E) { 133 | throw UnsupportedOperationException() 134 | } 135 | 136 | override fun hasNext(): Boolean { 137 | return iterator.hasNext() 138 | } 139 | 140 | override fun hasPrevious(): Boolean { 141 | return iterator.hasPrevious() 142 | } 143 | 144 | override fun next(): E { 145 | return iterator.next() 146 | } 147 | 148 | override fun nextIndex(): Int { 149 | return iterator.nextIndex() 150 | } 151 | 152 | override fun previous(): E { 153 | return iterator.previous() 154 | } 155 | 156 | override fun previousIndex(): Int { 157 | return iterator.previousIndex() 158 | } 159 | 160 | override fun remove() { 161 | iterator.remove() 162 | } 163 | 164 | override fun set(element: E) { 165 | throw UnsupportedOperationException() 166 | } 167 | } 168 | } 169 | 170 | override fun removeAt(index: Int): E { 171 | return list.removeAt(index) 172 | } 173 | 174 | override fun remove(element: E): Boolean { 175 | return list.remove(element) 176 | } 177 | 178 | override fun removeAll(elements: Collection): Boolean { 179 | return list.removeAll(elements) 180 | } 181 | 182 | override fun retainAll(elements: Collection): Boolean { 183 | return list.retainAll(elements) 184 | } 185 | 186 | override val size: Int 187 | get() { 188 | return list.size 189 | } 190 | 191 | override fun toArray(): Array { 192 | return list.toTypedArray() 193 | } 194 | 195 | override fun toArray(a: Array): Array { 196 | return list.toArray(a) 197 | } 198 | 199 | override fun toString(): String { 200 | return list.toString() 201 | } 202 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/config/EnumSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.config 19 | 20 | internal object EnumSupport { 21 | @Suppress("UNCHECKED_CAST") 22 | @JvmStatic 23 | fun valueOf(enumType: Class<*>, name: String): Enum<*> { 24 | return java.lang.Enum.valueOf(enumType as Class>, name) 25 | } 26 | 27 | @JvmStatic 28 | fun name(value: Any): String { 29 | return (value as Enum<*>).name 30 | } 31 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/data/PersistentDataKey.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.data 2 | 3 | import org.bukkit.NamespacedKey 4 | import org.bukkit.persistence.PersistentDataType 5 | 6 | /** 7 | * [PersistentDataSupport] 에서 사용하는 키입니다. 8 | * [NamespacedKey] 와 [PersistentDataType] 를 결합한 클래스입니다 9 | * 10 | * @author Monun 11 | */ 12 | data class PersistentDataKey( 13 | val namespacedKey: NamespacedKey, 14 | val dataType: PersistentDataType 15 | ) -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/DefaultProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.entity.Entity 21 | import org.bukkit.event.Event 22 | import org.bukkit.event.block.* 23 | import org.bukkit.event.enchantment.EnchantItemEvent 24 | import org.bukkit.event.enchantment.PrepareItemEnchantEvent 25 | import org.bukkit.event.entity.EntityEvent 26 | import org.bukkit.event.hanging.HangingBreakByEntityEvent 27 | import org.bukkit.event.hanging.HangingPlaceEvent 28 | import org.bukkit.event.inventory.FurnaceExtractEvent 29 | import org.bukkit.event.inventory.InventoryCloseEvent 30 | import org.bukkit.event.inventory.InventoryInteractEvent 31 | import org.bukkit.event.inventory.InventoryOpenEvent 32 | import org.bukkit.event.player.PlayerEvent 33 | import org.bukkit.event.vehicle.VehicleEvent 34 | 35 | @Suppress("unused") 36 | abstract class DefaultProvider private constructor() : EntityProvider { 37 | internal class BlockBreakEntityProvider : EntityProvider { 38 | override fun getFrom(event: BlockBreakEvent): Entity { 39 | return event.player 40 | } 41 | } 42 | 43 | internal class BlockDamageEntityProvider : EntityProvider { 44 | override fun getFrom(event: BlockDamageEvent): Entity { 45 | return event.player 46 | } 47 | } 48 | 49 | internal class BlockIgniteEntityProvider : EntityProvider { 50 | override fun getFrom(event: BlockIgniteEvent): Entity? { 51 | return event.ignitingEntity 52 | } 53 | } 54 | 55 | internal class BlockPlaceEntityProvider : EntityProvider { 56 | override fun getFrom(event: BlockPlaceEvent): Entity { 57 | return event.player 58 | } 59 | } 60 | 61 | internal class SignChangeEntityProvider : EntityProvider { 62 | override fun getFrom(event: SignChangeEvent): Entity { 63 | return event.player 64 | } 65 | } 66 | 67 | internal class EnchantItemEntityProvider : EntityProvider { 68 | override fun getFrom(event: EnchantItemEvent): Entity { 69 | return event.enchanter 70 | } 71 | } 72 | 73 | internal class PrepareItemEnchantEntityProvider : EntityProvider { 74 | override fun getFrom(event: PrepareItemEnchantEvent): Entity { 75 | return event.enchanter 76 | } 77 | } 78 | 79 | internal class EntityEntityProvider : EntityProvider { 80 | override fun getFrom(event: EntityEvent): Entity { 81 | return event.entity 82 | } 83 | } 84 | 85 | internal class HangingBreakByEntityEntityProvider : EntityProvider { 86 | override fun getFrom(event: HangingBreakByEntityEvent): Entity? { 87 | return event.remover 88 | } 89 | } 90 | 91 | internal class HangingPlaceEntityProvider : EntityProvider { 92 | override fun getFrom(event: HangingPlaceEvent): Entity? { 93 | return event.player 94 | } 95 | } 96 | 97 | internal class FurnaceExtractEntityProvider : EntityProvider { 98 | override fun getFrom(event: FurnaceExtractEvent): Entity { 99 | return event.player 100 | } 101 | } 102 | 103 | internal class InventoryCloseEntityProvider : EntityProvider { 104 | override fun getFrom(event: InventoryCloseEvent): Entity { 105 | return event.player 106 | } 107 | } 108 | 109 | internal class InventoryInteractEntityProvider : EntityProvider { 110 | override fun getFrom(event: InventoryInteractEvent): Entity { 111 | return event.whoClicked 112 | } 113 | } 114 | 115 | internal class InventoryOpenEntityProvider : EntityProvider { 116 | override fun getFrom(event: InventoryOpenEvent): Entity { 117 | return event.player 118 | } 119 | } 120 | 121 | internal class PlayerProvider : EntityProvider { 122 | override fun getFrom(event: PlayerEvent): Entity { 123 | return event.player 124 | } 125 | } 126 | 127 | internal class VehicleProvider : EntityProvider { 128 | override fun getFrom(event: VehicleEvent): Entity { 129 | return event.vehicle 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EntityEventManager.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import com.google.common.collect.MapMaker 21 | import io.github.monun.tap.event.EventTools.getRegistrationClass 22 | import org.bukkit.entity.Entity 23 | import org.bukkit.entity.Player 24 | import org.bukkit.event.Event 25 | import org.bukkit.event.EventPriority 26 | import org.bukkit.event.HandlerList 27 | import org.bukkit.event.Listener 28 | import org.bukkit.plugin.EventExecutor 29 | import org.bukkit.plugin.Plugin 30 | 31 | @Suppress("unused") 32 | /** 33 | * 지정한 [Entity] 전용 이벤트를 처리하는 클래스 34 | * 이 클래스는 Thread-Unsafe 입니다. 35 | * Async된 [Event]는 지원이 불확실합니다 36 | */ 37 | class EntityEventManager @JvmOverloads constructor( 38 | private val plugin: Plugin, 39 | private val priority: EventPriority = EventPriority.NORMAL 40 | ) { 41 | private val statements = HashMap, ListenerStatement>() 42 | 43 | private val listeners = HashMap, EventListener>() 44 | 45 | private val entities = MapMaker().weakKeys().makeMap() 46 | 47 | private val eventExecutor = EventExecutor { listener: Listener, event: Event -> 48 | (listener as EventListener).onEvent(event) 49 | } 50 | 51 | /** 52 | * 지정한 [Entity] 전용 이벤트 리스너를 등록합니다. 53 | * 54 | * @param entity 대상 55 | * @param listener 이벤트리스너 56 | */ 57 | fun registerEvents(entity: Entity, listener: Listener): RegisteredEntityListener { 58 | require(entity.isValid || (entity is Player && entity.isOnline)) { "Invalid entity: $entity" } 59 | 60 | val listenerStatement = createRegisteredListenerStatement(listener.javaClass) 61 | val eventEntity = entities.computeIfAbsent(entity) { EventEntity() } 62 | 63 | val registeredEntityListener = RegisteredEntityListener(eventEntity, listenerStatement, listener) 64 | eventEntity.register(registeredEntityListener) 65 | 66 | return registeredEntityListener 67 | } 68 | 69 | private fun createRegisteredListenerStatement(listenerClass: Class<*>): ListenerStatement { 70 | return statements.computeIfAbsent(listenerClass) { clazz: Class<*> -> 71 | val statement = ListenerStatement.getOrCreate(clazz) 72 | 73 | for (statementStatement in statement.handlerStatements) { 74 | registerEvent(statementStatement) 75 | } 76 | 77 | statement 78 | } 79 | } 80 | 81 | private fun registerEvent(statement: HandlerStatement) { 82 | val registrationClass = statement.registrationClass 83 | 84 | val listener = listeners.computeIfAbsent(registrationClass) { clazz: Class<*> -> 85 | val newListener = EventListener() 86 | plugin.server.pluginManager.registerEvent( 87 | clazz.asSubclass(Event::class.java), 88 | newListener, 89 | priority, 90 | eventExecutor, 91 | plugin, 92 | false 93 | ) 94 | 95 | newListener 96 | } 97 | 98 | listener.addProvider(statement.provider) 99 | } 100 | 101 | /** 102 | * 지정한 [Entity] 전용 이벤트 리스너를 제거합니다. 103 | * 104 | * @param entity 대상 105 | * @param listener 이벤트리스너 106 | */ 107 | fun unregisterEvent(entity: Entity, listener: Listener) { 108 | val eventEntity = entities[entity] 109 | 110 | if (eventEntity != null) { 111 | val statement = statements[listener.javaClass] 112 | 113 | if (statement != null) { 114 | eventEntity.unregister(statement, listener) 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * 등록된 모든 리스너를 제거합니다. 121 | */ 122 | fun unregisterAll() { 123 | for (eventEntity in entities.values) { 124 | eventEntity.unregisterAll() 125 | } 126 | 127 | for (listener in listeners.values) { 128 | HandlerList.unregisterAll(listener) 129 | } 130 | 131 | entities.clear() 132 | listeners.clear() 133 | statements.clear() 134 | } 135 | 136 | private inner class EventListener : Listener { 137 | private val providers = LinkedHashSet() 138 | 139 | private var bake: Array? = null 140 | 141 | fun onEvent(event: Event) { 142 | for (provider in getBake()) { 143 | val eventClass = event.javaClass 144 | 145 | if (provider.eventClass.isAssignableFrom(eventClass)) { 146 | val entity = provider.provider.getFrom(event) 147 | 148 | if (entity != null) { 149 | val eventEntity = entities[entity] 150 | 151 | if (eventEntity != null) { 152 | val regClass = getRegistrationClass(eventClass) 153 | val handlers = eventEntity.getHandlerList(regClass) 154 | 155 | handlers?.callEvent(event, provider) 156 | } 157 | } 158 | } 159 | } 160 | } 161 | 162 | private fun getBake(): Array { 163 | val bake = bake 164 | return bake ?: providers.toTypedArray().also { this.bake = it } 165 | } 166 | 167 | fun addProvider(provider: EventEntityProvider) { 168 | providers.add(provider) 169 | bake = null 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EntityHandlerList.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import io.github.monun.tap.collection.SortedList 21 | import org.bukkit.event.Event 22 | import org.bukkit.event.Listener 23 | 24 | class EntityHandlerList { 25 | private val handlerList = SortedList() 26 | private var handlers: Array? = null 27 | 28 | @Synchronized 29 | fun register(handler: RegisteredEntityHandler) { 30 | handlers = null 31 | handlerList.add(handler) 32 | } 33 | 34 | @Synchronized 35 | fun unregister(handler: RegisteredEntityHandler) { 36 | handlers = null 37 | handlerList.binaryRemove(handler) 38 | } 39 | 40 | fun unregister(listener: Listener) { 41 | handlers = null 42 | handlerList.removeIf { handler: RegisteredEntityHandler -> 43 | if (listener === handler.listener) { 44 | handler.remove() 45 | return@removeIf true 46 | } 47 | 48 | false 49 | } 50 | } 51 | 52 | @Synchronized 53 | fun bake() { 54 | if (handlers != null) return 55 | handlers = handlerList.toTypedArray() 56 | } 57 | 58 | private val registeredHandlers: Array 59 | get() { 60 | var handlers = handlers 61 | 62 | while (handlers == null) { 63 | bake() 64 | handlers = this.handlers 65 | } 66 | 67 | return handlers 68 | } 69 | 70 | fun callEvent(event: Event, provider: EventEntityProvider) { 71 | for (handler in registeredHandlers) { 72 | if (provider === handler.statement.provider) { 73 | handler.callEvent(event) 74 | } 75 | } 76 | } 77 | 78 | fun unregisterAll() { 79 | for (registeredEntityHandler in handlerList) { 80 | registeredEntityHandler.remove() 81 | } 82 | 83 | handlerList.clear() 84 | handlers = null 85 | } 86 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EntityProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.entity.Entity 21 | import org.bukkit.entity.Projectile 22 | import org.bukkit.event.Event 23 | import org.bukkit.event.entity.* 24 | import org.bukkit.event.player.PlayerInteractEntityEvent 25 | 26 | /** 27 | * 이벤트를 수신할 대상을 지정합니다. 28 | * [EntityDamageByEntityEvent]와 같이 [Entity]가 여러개 포함된 이벤트일 경우 29 | * [EntityProvider.EntityDamageByEntity.Damager]를 사용하여 공격자를 대상으로 지정할 수 있습니다. 30 | */ 31 | @Suppress("unused") 32 | fun interface EntityProvider { 33 | fun getFrom(event: T): Entity? 34 | 35 | class PlayerPickupItem { 36 | class PickupItem : EntityProvider { 37 | override fun getFrom(event: EntityPickupItemEvent): Entity { 38 | return event.item 39 | } 40 | } 41 | } 42 | 43 | class PlayerInteractEntity { 44 | class Clicked : EntityProvider { 45 | override fun getFrom(event: PlayerInteractEntityEvent): Entity { 46 | return event.rightClicked 47 | } 48 | } 49 | } 50 | 51 | class EntityDeath { 52 | class Killer : EntityProvider { 53 | override fun getFrom(event: EntityDeathEvent): Entity? { 54 | return event.entity.killer 55 | } 56 | } 57 | } 58 | 59 | class EntityDamageByEntity { 60 | class Damager : EntityProvider { 61 | override fun getFrom(event: EntityDamageByEntityEvent): Entity { 62 | return event.damager 63 | } 64 | } 65 | 66 | class Shooter : EntityProvider { 67 | override fun getFrom(event: EntityDamageByEntityEvent): Entity? { 68 | val damager = event.damager 69 | 70 | if (damager is Projectile) { 71 | val source = damager.shooter 72 | if (source is Entity) return source 73 | } 74 | 75 | return null 76 | } 77 | } 78 | } 79 | 80 | class EntityTarget { 81 | class Target : EntityProvider { 82 | override fun getFrom(event: EntityTargetEvent): Entity? { 83 | return event.target 84 | } 85 | } 86 | } 87 | 88 | class EntityTame { 89 | class Owner : EntityProvider { 90 | override fun getFrom(event: EntityTameEvent): Entity? { 91 | return event.owner.takeIf { it is Entity } as Entity? 92 | } 93 | } 94 | } 95 | 96 | class ProjectileLaunch { 97 | class Shooter : EntityProvider { 98 | override fun getFrom(event: ProjectileLaunchEvent): Entity? { 99 | return event.entity.shooter?.takeIf { it is Entity } as Entity? 100 | } 101 | } 102 | } 103 | 104 | class ProjectileHit { 105 | class Shooter : EntityProvider { 106 | override fun getFrom(event: ProjectileHitEvent): Entity? { 107 | return event.entity.shooter?.takeIf { it is Entity } as Entity? 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EventEntity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.event.Listener 21 | import java.util.concurrent.ConcurrentHashMap 22 | 23 | class EventEntity { 24 | private val slots = ConcurrentHashMap, EntityHandlerList>() 25 | 26 | fun register(registeredEntityListener: RegisteredEntityListener) { 27 | for (handler in registeredEntityListener.handlers) { 28 | val statement = handler.statement 29 | val handlerList = slots.computeIfAbsent(statement.registrationClass) { EntityHandlerList() } 30 | handlerList.register(handler) 31 | } 32 | } 33 | 34 | fun unregister(registeredListener: RegisteredEntityListener) { 35 | for (handler in registeredListener.handlers) { 36 | handler.remove() 37 | val handlerList = slots[handler.statement.registrationClass] 38 | handlerList?.unregister(handler) 39 | } 40 | } 41 | 42 | fun unregister(statement: ListenerStatement, listener: Listener) { 43 | for (handlerStatement in statement.handlerStatements) { 44 | val handlerList = slots[handlerStatement.registrationClass] 45 | handlerList?.unregister(listener) 46 | } 47 | } 48 | 49 | fun getHandlerList(eventClass: Class<*>): EntityHandlerList? { 50 | return slots[eventClass] 51 | } 52 | 53 | fun unregisterAll() { 54 | for (handlerList in slots.values) { 55 | handlerList.unregisterAll() 56 | } 57 | 58 | slots.clear() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EventEntityProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import io.github.monun.tap.event.EventTools.getGenericEventType 21 | import org.bukkit.event.Event 22 | 23 | class EventEntityProvider internal constructor(val eventClass: Class<*>, val provider: EntityProvider) { 24 | internal constructor(provider: EntityProvider) : this(getGenericEventType(provider.javaClass), provider) 25 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/EventTools.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.event.Event 21 | import org.bukkit.plugin.IllegalPluginAccessException 22 | import java.lang.reflect.ParameterizedType 23 | import java.util.* 24 | 25 | object EventTools { 26 | private val CUSTOM_PROVIDERS = WeakHashMap, EventEntityProvider>() 27 | private val DEFAULT_PROVIDERS: Array 28 | 29 | /** 30 | * [Event]를 상속한 클래스들 중 [org.bukkit.event.HandlerList]가 있는 클래스를 찾아서 반환합니다. 31 | */ 32 | @JvmStatic 33 | fun getRegistrationClass(clazz: Class<*>): Class<*> { 34 | return try { 35 | clazz.getDeclaredMethod("getHandlerList") 36 | clazz 37 | } catch (e: NoSuchMethodException) { 38 | if (clazz.superclass != null 39 | && clazz.superclass != Event::class.java 40 | && Event::class.java.isAssignableFrom(clazz.superclass) 41 | ) { 42 | getRegistrationClass(clazz.superclass.asSubclass(Event::class.java)) 43 | } else { 44 | throw IllegalPluginAccessException("Unable to find handler list for event ${clazz.name}. Static getHandlerList method required!") 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * [DefaultProvider]에서 호환 가능한 제공자를 반환합니다. 51 | * 52 | * @param eventClass 찾아낼 클래스 53 | * @return 호환되는 엔티티 제공자 54 | * @see DefaultProvider 55 | */ 56 | @JvmStatic 57 | fun findDefaultProvider(eventClass: Class<*>): EventEntityProvider { 58 | for (provider in DEFAULT_PROVIDERS) { 59 | if (provider.eventClass.isAssignableFrom(eventClass)) 60 | return provider 61 | } 62 | 63 | throw IllegalArgumentException("Not found DefaultProvider for $eventClass") 64 | } 65 | 66 | @Suppress("UNCHECKED_CAST") 67 | @JvmStatic 68 | fun getOrCreateCustomProvider(providerClass: Class<*>): EventEntityProvider { 69 | return CUSTOM_PROVIDERS.computeIfAbsent(providerClass) { clazz: Class<*> -> 70 | try { 71 | return@computeIfAbsent EventEntityProvider( 72 | clazz.asSubclass(EntityProvider::class.java).getConstructor().newInstance() as EntityProvider 73 | ) 74 | } catch (e: InstantiationException) { 75 | throw AssertionError(e) 76 | } catch (e: IllegalAccessException) { 77 | throw AssertionError(e) 78 | } 79 | } 80 | } 81 | 82 | @JvmStatic 83 | fun getGenericEventType(providerClass: Class<*>): Class<*> { 84 | var clazz = providerClass 85 | val prefix = EntityProvider::class.java.name + "<" //제너릭 타임 이름은 ClassName으로 반환됨 86 | val genericInterfaces = clazz.genericInterfaces 87 | 88 | do { 89 | for (genericInterface in genericInterfaces) { 90 | if (genericInterface.typeName.startsWith(prefix)) { 91 | return (genericInterface as ParameterizedType).actualTypeArguments[0] as Class<*> 92 | } 93 | } 94 | } while (clazz.superclass.also { clazz = it } != Any::class.java) 95 | 96 | throw IllegalArgumentException("$clazz is not EntityProvider") 97 | } 98 | 99 | init { 100 | // 기본 개체 제공자 초기화 101 | val classes = DefaultProvider::class.java.declaredClasses 102 | val defaultProviders = ArrayList(classes.size) 103 | 104 | for (clazz in classes) { 105 | if (EntityProvider::class.java.isAssignableFrom(clazz)) { 106 | try { 107 | @Suppress("UNCHECKED_CAST") 108 | defaultProviders.add( 109 | EventEntityProvider( 110 | clazz.getConstructor().newInstance() as EntityProvider 111 | ) 112 | ) 113 | } catch (e: Exception) { 114 | throw AssertionError(e) 115 | } 116 | } 117 | } 118 | 119 | DEFAULT_PROVIDERS = defaultProviders.toTypedArray() 120 | } 121 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/HandlerStatement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.event.EventPriority 21 | import org.bukkit.plugin.EventExecutor 22 | 23 | class HandlerStatement( 24 | val eventClass: Class<*>, 25 | val registrationClass: Class<*>, 26 | val provider: EventEntityProvider, 27 | val priority: EventPriority, 28 | val isIgnoreCancelled: Boolean, 29 | val executor: EventExecutor 30 | ) -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/ListenerStatement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import com.google.common.collect.ImmutableList 21 | import com.google.common.reflect.TypeToken 22 | import org.bukkit.event.Event 23 | import org.bukkit.event.EventHandler 24 | import org.bukkit.event.Listener 25 | import org.bukkit.plugin.EventExecutor 26 | import java.lang.reflect.Method 27 | import java.lang.reflect.Modifier 28 | import java.util.* 29 | 30 | @Suppress("unused") 31 | class ListenerStatement(val listenerClass: Class<*>, handlerStatements: ArrayList) { 32 | val handlerStatements: ImmutableList = ImmutableList.copyOf(handlerStatements) 33 | 34 | companion object { 35 | private val STATEMENTS: MutableMap, ListenerStatement> = WeakHashMap() 36 | 37 | @JvmStatic 38 | fun getOrCreate(listenerClass: Class<*>): ListenerStatement { 39 | return STATEMENTS.computeIfAbsent(listenerClass) { 40 | val mod = listenerClass.modifiers 41 | 42 | require(Modifier.isPublic(mod)) { "EntityListener modifier must be public" } 43 | 44 | val handlerStatements = ArrayList() 45 | val methods = listenerClass.methods 46 | 47 | @Suppress("UnstableApiUsage") 48 | val supers = TypeToken.of(listenerClass).types.rawTypes() 49 | 50 | for (method in methods) { 51 | for (superClass in supers) { 52 | if (!Listener::class.java.isAssignableFrom(superClass)) 53 | break 54 | 55 | try { 56 | val real = superClass.getDeclaredMethod(method.name, *method.parameterTypes) 57 | 58 | if (real.isAnnotationPresent(EventHandler::class.java)) { 59 | try { 60 | handlerStatements.add(createHandlerStatement(method)) 61 | } catch (e: Exception) { 62 | throw IllegalArgumentException("Failed to create HandlerStatement for $real") 63 | } 64 | 65 | break 66 | } 67 | } catch (ignored: NoSuchMethodException) { 68 | } catch (ignored: SecurityException) { 69 | } 70 | } 71 | } 72 | ListenerStatement(listenerClass, handlerStatements) 73 | } 74 | } 75 | 76 | private fun createHandlerStatement(method: Method): HandlerStatement { 77 | val parameterTypes = method.parameterTypes 78 | 79 | require(parameterTypes.size == 1) { "EntityHandler methods must require a single argument: $method" } 80 | 81 | val eventClass = parameterTypes[0] 82 | 83 | require(Event::class.java.isAssignableFrom(eventClass)) { "'${eventClass.name}' is not event class: $method" } 84 | 85 | val handler = method.getAnnotation(EventHandler::class.java) 86 | val registrationClass = EventTools.getRegistrationClass(eventClass) 87 | 88 | val targetEntity = method.getAnnotation(TargetEntity::class.java) 89 | val provider = if (targetEntity == null) { 90 | EventTools.findDefaultProvider(eventClass) 91 | } else { 92 | EventTools.getOrCreateCustomProvider(targetEntity.value.java) 93 | } 94 | 95 | val executor = EventExecutor.create(method, eventClass.asSubclass(Event::class.java)) 96 | 97 | return HandlerStatement( 98 | eventClass, 99 | registrationClass, 100 | provider, 101 | handler.priority, 102 | handler.ignoreCancelled, 103 | executor 104 | ) 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/RegisteredEntityHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import org.bukkit.event.Cancellable 21 | import org.bukkit.event.Event 22 | import org.bukkit.event.EventException 23 | import org.bukkit.event.Listener 24 | 25 | class RegisteredEntityHandler(val statement: HandlerStatement, val listener: Listener) : 26 | Comparable { 27 | private val generatedTime = System.currentTimeMillis() 28 | 29 | var isValid = true 30 | private set 31 | 32 | override operator fun compareTo(other: RegisteredEntityHandler): Int { 33 | val comp = statement.priority.compareTo(other.statement.priority) 34 | return if (comp != 0) comp else generatedTime.compareTo(other.generatedTime) 35 | } 36 | 37 | fun callEvent(event: Event) { 38 | if (statement.isIgnoreCancelled && event is Cancellable && (event as Cancellable).isCancelled) return 39 | 40 | try { 41 | statement.executor.execute(listener, event) 42 | } catch (e: EventException) { 43 | e.printStackTrace() 44 | } 45 | } 46 | 47 | fun remove() { 48 | isValid = false 49 | } 50 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/RegisteredEntityListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import com.google.common.collect.ImmutableList 21 | import org.bukkit.event.Listener 22 | 23 | @Suppress("unused", "MemberVisibilityCanBePrivate", "CanBeParameter") 24 | class RegisteredEntityListener( 25 | private val eventEntity: EventEntity, 26 | val statement: ListenerStatement, 27 | val listener: Listener 28 | ) { 29 | val handlers: ImmutableList 30 | 31 | fun unregister() { 32 | eventEntity.unregister(this) 33 | } 34 | 35 | init { 36 | val handlerStatements = statement.handlerStatements 37 | val handlers = ArrayList(handlerStatements.size) 38 | 39 | for (handlerStatement in handlerStatements) { 40 | handlers.add(RegisteredEntityHandler(handlerStatement, listener)) 41 | } 42 | 43 | this.handlers = ImmutableList.copyOf(handlers) 44 | } 45 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/event/TargetEntity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.event 19 | 20 | import kotlin.reflect.KClass 21 | 22 | /** 23 | * 이벤트를 수신할 대상을 지정합니다. 24 | * [EntityProvider]를 구현한 클래스를 지정할 수 있습니다. 25 | */ 26 | @Retention(AnnotationRetention.RUNTIME) 27 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) 28 | annotation class TargetEntity(val value: KClass>) 29 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeEntity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import io.github.monun.tap.protocol.AnimationType 21 | import io.github.monun.tap.protocol.PacketContainer 22 | import org.bukkit.EntityEffect 23 | import org.bukkit.Location 24 | import org.bukkit.entity.Entity 25 | import org.bukkit.entity.Player 26 | import org.bukkit.inventory.EntityEquipment 27 | 28 | interface FakeEntity { 29 | val server: FakeEntityServer 30 | val bukkitEntity: T 31 | val location: Location 32 | val vehicle: FakeEntity<*>? 33 | val passengers: List<*> 34 | val valid: Boolean 35 | val dead: Boolean 36 | var isVisible: Boolean 37 | 38 | fun addPassenger(passenger: FakeEntity<*>): Boolean 39 | 40 | fun removePassenger(passenger: FakeEntity<*>): Boolean 41 | 42 | fun eject(): Boolean 43 | 44 | fun moveTo(target: Location) 45 | 46 | fun move(x: Double, y: Double, z: Double) { 47 | moveTo(location.add(x, y, z)) 48 | } 49 | 50 | fun moveAndRotation(x: Double, y: Double, z: Double, yaw: Float, pitch: Float) { 51 | moveTo(location.add(x, y, z).apply { 52 | this.yaw = yaw 53 | this.pitch = pitch 54 | }) 55 | } 56 | 57 | fun rotate(yaw: Float, pitch: Float) 58 | 59 | fun updateMetadata(applier: T.() -> Unit) 60 | 61 | fun updateEquipment(applier: EntityEquipment.() -> Unit) 62 | 63 | fun playEffect(data: Byte) 64 | 65 | @Suppress("DEPRECATION") 66 | fun playEffect(type: EntityEffect) = playEffect(type.data) 67 | 68 | fun playAnimation(action: Int) 69 | 70 | fun playAnimation(action: AnimationType) 71 | 72 | /** 73 | * 1.19.4 이상에서만 동작합니다. 74 | */ 75 | fun playHurtAnimation() 76 | 77 | fun excludeTracker(player: Player) 78 | 79 | fun includeTracker(player: Player) 80 | 81 | fun broadcast(packet: () -> PacketContainer) 82 | 83 | fun broadcast(packet: PacketContainer) = broadcast { packet } 84 | 85 | fun broadcastImmediately(packet: PacketContainer) = broadcast { packet } 86 | 87 | fun remove() 88 | } 89 | 90 | fun FakeEntity.updateSkinParts(skinParts: FakeSkinParts) { 91 | updateMetadata { 92 | FakeSupportNMS.setSkinParts(this, skinParts.raw) 93 | } 94 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeEntityServer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import com.destroystokyo.paper.profile.ProfileProperty 21 | import io.github.monun.tap.loader.LibraryLoader 22 | import org.bukkit.Location 23 | import org.bukkit.block.data.BlockData 24 | import org.bukkit.entity.Entity 25 | import org.bukkit.entity.FallingBlock 26 | import org.bukkit.entity.Item 27 | import org.bukkit.entity.Player 28 | import org.bukkit.inventory.ItemStack 29 | import org.bukkit.plugin.java.JavaPlugin 30 | import java.util.* 31 | 32 | interface FakeEntityServer { 33 | companion object : FakeInternal by LibraryLoader.loadImplement(FakeInternal::class.java) 34 | 35 | /** 36 | * 스폰거리 37 | * 38 | * [Player]와 [FakeEntity]의 거리가 [spawnDistance]보다 작을 때 클라이언트에 스폰됨 39 | * 40 | * 디스폰 거리보다 작아야함 41 | * 42 | * @exception IllegalArgumentException 43 | */ 44 | var spawnDistance: Double 45 | 46 | /** 47 | * [FakeEntity] 디스폰 거리 48 | * 49 | * [Player]와 [FakeEntity]의 거리가 [spawnDistance]보다 클 때 클라이언트에서 디스폰됨 50 | * 51 | * 스폰 거리보다 커야함 52 | * 53 | * @exception IllegalArgumentException 54 | */ 55 | var despawnDistance: Double 56 | 57 | val entities: List> 58 | 59 | fun spawnEntity(location: Location, clazz: Class): FakeEntity 60 | 61 | fun spawnFallingBlock(location: Location, blockData: BlockData): FakeEntity 62 | 63 | fun spawnItem(location: Location, item: ItemStack): FakeEntity 64 | 65 | fun spawnPlayer( 66 | location: Location, 67 | name: String, 68 | profileProperties: Set = emptySet(), 69 | skinParts: FakeSkinParts = defaultFakeSkinParts, 70 | uniqueId: UUID = UUID.randomUUID() 71 | ): FakeEntity 72 | 73 | fun addPlayer(player: Player) 74 | 75 | fun removePlayer(player: Player) 76 | 77 | fun update() 78 | 79 | fun clear() 80 | 81 | fun shutdown() 82 | } 83 | 84 | private val defaultFakeSkinParts = FakeSkinParts() 85 | 86 | interface FakeInternal { 87 | fun create(plugin: JavaPlugin): FakeEntityServer 88 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeProjectile.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import io.github.monun.tap.math.copyTo 21 | import io.github.monun.tap.math.vector 22 | import org.bukkit.Location 23 | import org.bukkit.util.Vector 24 | import java.util.* 25 | 26 | open class FakeProjectile( 27 | var maxTicks: Int, 28 | var range: Double 29 | ) { 30 | private lateinit var _previousLocation: Location 31 | private lateinit var _location: Location 32 | private lateinit var _targetLocation: Location 33 | private val _velocity: Vector = Vector() 34 | 35 | val previousLocation: Location 36 | get() = _previousLocation.clone() 37 | 38 | val location: Location 39 | get() = _location.clone() 40 | 41 | var targetLocation: Location 42 | get() = _targetLocation.clone() 43 | set(value) = _targetLocation.copyTo(value) 44 | 45 | var velocity: Vector 46 | get() = _velocity.clone() 47 | set(value) { 48 | _velocity.copy(value) 49 | 50 | if (this::_targetLocation.isInitialized) { 51 | _targetLocation.apply { 52 | copyTo(_location) 53 | add(value) 54 | } 55 | } 56 | } 57 | 58 | var ticks: Int = 0 59 | private set 60 | 61 | var distanceFlown: Double = 0.0 62 | private set 63 | 64 | val availableRange: Double 65 | get() = range - distanceFlown 66 | 67 | var launched: Boolean = false 68 | internal set 69 | 70 | var isValid: Boolean = true 71 | private set 72 | 73 | private val trailQueue = ArrayDeque(2) 74 | 75 | internal fun init(location: Location) { 76 | _previousLocation = location.clone() 77 | _location = location.clone() 78 | _targetLocation = location.clone().add(_velocity) 79 | } 80 | 81 | internal fun update() { 82 | if (!isValid) return 83 | 84 | ticks++ 85 | 86 | runCatching { onPreUpdate() } 87 | 88 | val previous = _previousLocation 89 | val current = _location 90 | val target = _targetLocation 91 | var vector: Vector? = null 92 | 93 | val movement = Movement(current.clone(), target.clone()) 94 | 95 | onMove(movement) 96 | target.copyTo(movement.to) 97 | previous.copyTo(current) 98 | current.copyTo(target) 99 | 100 | if (previous.world === current.world) { 101 | vector = previous vector current 102 | current.direction = vector 103 | 104 | distanceFlown += previous.distance(current) 105 | } 106 | 107 | var mortal = false 108 | 109 | if (ticks >= maxTicks || distanceFlown >= range) { 110 | // 비행시간을 모두 소모하거나 최대 사거리를 넘은경우 제거 111 | mortal = true 112 | } else { 113 | // 다음 틱 이동 준비 114 | var velocity = _velocity 115 | var speed = velocity.length() 116 | // 0 속도 피하기, normalize할때 무한됨 117 | if (speed != 0.0) { 118 | val availableRange = availableRange 119 | // 남은 사거리가 현재 속력보다 작을경우 최대 사거리를 넘지 않기 위해 속력을 남은 사거리로 보정 120 | if (availableRange < speed) { 121 | speed = availableRange 122 | velocity = velocity.clone().apply { 123 | x /= speed 124 | y /= speed 125 | z /= speed 126 | multiply(availableRange) 127 | } 128 | } 129 | } 130 | 131 | target.add(velocity) 132 | } 133 | 134 | val trailQueue = this.trailQueue 135 | 136 | trailQueue += Trail(previous.clone(), current.clone(), vector) 137 | 138 | while (trailQueue.count() > 3) { 139 | val trail = trailQueue.remove() 140 | 141 | onTrail(trail) 142 | } 143 | 144 | if (mortal) 145 | remove() 146 | 147 | runCatching { onPostUpdate() } 148 | } 149 | 150 | fun remove() { 151 | if (isValid) { 152 | isValid = false 153 | trailQueue.clear() 154 | 155 | runCatching { onRemove() } 156 | } 157 | } 158 | 159 | protected open fun onPreUpdate() {} 160 | protected open fun onPostUpdate() {} 161 | protected open fun onMove(movement: Movement) {} 162 | protected open fun onTrail(trail: Trail) {} 163 | protected open fun onRemove() {} 164 | 165 | fun checkState() { 166 | require(isValid) { "Invalid ${this.javaClass.simpleName}@${System.identityHashCode(this).toString(0x10)}" } 167 | } 168 | } 169 | 170 | class Movement( 171 | var from: Location, 172 | var to: Location 173 | ) 174 | 175 | class Trail( 176 | val from: Location, 177 | val to: Location, 178 | val velocity: Vector? 179 | ) -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeProjectileManager.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import com.google.common.collect.ImmutableList 21 | import org.bukkit.Location 22 | 23 | class FakeProjectileManager { 24 | val projectiles: List 25 | get() = ImmutableList.copyOf(_projectiles) 26 | 27 | private val _projectiles = ArrayList() 28 | 29 | fun launch(location: Location, projectile: FakeProjectile) { 30 | projectile.checkState() 31 | require(!projectile.launched) { "Already launched projectile" } 32 | 33 | projectile.init(location) 34 | _projectiles += projectile 35 | } 36 | 37 | fun update() { 38 | updateProjectiles() 39 | } 40 | 41 | private fun updateProjectiles() { 42 | val projectiles = _projectiles 43 | val iterator = projectiles.iterator() 44 | 45 | while (iterator.hasNext()) { 46 | val projectile = iterator.next() 47 | 48 | projectile.update() 49 | 50 | if (!projectile.isValid) 51 | iterator.remove() 52 | } 53 | } 54 | 55 | fun clear() { 56 | for (projectile in _projectiles) { 57 | projectile.remove() 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeSkinParts.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import com.destroystokyo.paper.SkinParts 21 | 22 | class FakeSkinParts( 23 | raw: Int = 0b1111111 24 | ) { 25 | companion object { 26 | fun from(parts: SkinParts) = FakeSkinParts(parts.raw) 27 | } 28 | 29 | var raw: Int = raw 30 | private set 31 | 32 | fun has(part: SkinPart): Boolean { 33 | return raw and part.bit != 0 34 | } 35 | 36 | fun enable(part: SkinPart) { 37 | raw = raw or part.bit 38 | } 39 | 40 | operator fun plusAssign(part: SkinPart) { 41 | enable(part) 42 | } 43 | 44 | fun disable(part: SkinPart) { 45 | raw = raw and part.bit.inv() 46 | } 47 | 48 | operator fun minusAssign(part: SkinPart) { 49 | disable(part) 50 | } 51 | 52 | fun enableAll() { 53 | raw = 0b1111111 54 | } 55 | 56 | fun disableAll() { 57 | raw = 0 58 | } 59 | } 60 | 61 | enum class SkinPart { 62 | CAPE, 63 | JACKET, 64 | LEFT_SLEEVE, 65 | RIGHT_SLEEVE, 66 | LEFT_PANTS, 67 | RIGHT_PANTS, 68 | HATS; 69 | 70 | val bit: Int = 1 shl ordinal 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/fake/FakeSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake 19 | 20 | import com.destroystokyo.paper.profile.PlayerProfile 21 | import com.destroystokyo.paper.profile.ProfileProperty 22 | import io.github.monun.tap.loader.LibraryLoader 23 | import io.github.monun.tap.protocol.PacketContainer 24 | import org.bukkit.Bukkit 25 | import org.bukkit.Location 26 | import org.bukkit.World 27 | import org.bukkit.block.data.BlockData 28 | import org.bukkit.entity.Entity 29 | import org.bukkit.entity.FallingBlock 30 | import org.bukkit.entity.Item 31 | import org.bukkit.entity.Player 32 | import org.bukkit.entity.Pose 33 | import org.bukkit.inventory.ItemStack 34 | import java.util.* 35 | 36 | /** 37 | * @author Nemo 38 | */ 39 | interface FakeSupport { 40 | fun getNetworkId(entity: Entity): Int 41 | 42 | fun createEntity(entityClass: Class, world: World): T 43 | 44 | fun setLocation(entity: Entity, loc: Location) 45 | 46 | fun setInvisible(entity: Entity, invisible: Boolean) 47 | 48 | fun isInvisible(entity: Entity): Boolean 49 | 50 | fun setPose(entity: Entity, pose: Pose) 51 | 52 | fun getMountedYOffset(entity: Entity): Double 53 | 54 | fun getYOffset(entity: Entity): Double 55 | 56 | fun createSpawnPacket(entity: Entity): Array 57 | 58 | fun createFallingBlock(blockData: BlockData): FallingBlock 59 | 60 | fun createItemEntity(item: ItemStack): Item 61 | fun createPlayerEntity( 62 | name: String, 63 | profileProperties: Set, 64 | skinParts: FakeSkinParts, 65 | uniqueId: UUID 66 | ): Player 67 | 68 | fun setSkinParts(player: Player, raw: Int) 69 | } 70 | 71 | internal val FakeSupportNMS = LibraryLoader.loadNMS(FakeSupport::class.java) 72 | 73 | @JvmInline 74 | value class TapEntity(val entity: Entity) { 75 | val networkId 76 | get() = FakeSupportNMS.getNetworkId(entity) 77 | 78 | var pose: Pose 79 | get() = entity.pose 80 | set(value) { 81 | FakeSupportNMS.setPose(entity, value) 82 | } 83 | 84 | var isInvisible 85 | get() = FakeSupportNMS.isInvisible(entity) 86 | set(value) { 87 | FakeSupportNMS.setInvisible(entity, value) 88 | } 89 | 90 | val mountedYOffset 91 | get() = FakeSupportNMS.getMountedYOffset(entity) 92 | 93 | val yOffset 94 | get() = FakeSupportNMS.getYOffset(entity) 95 | 96 | var location: Location 97 | get() = entity.location 98 | set(value) { 99 | FakeSupportNMS.setLocation(entity, value) 100 | } 101 | } 102 | 103 | fun Entity.tap() = TapEntity(this) 104 | 105 | fun Class.createFakeEntity(world: World = Bukkit.getWorlds().first()): T { 106 | return FakeSupportNMS.createEntity(this, world) 107 | } 108 | 109 | fun Entity.createSpawnPacket(): Array { 110 | return FakeSupportNMS.createSpawnPacket(this) 111 | } 112 | 113 | fun BlockData.createFallingBlock(): FallingBlock { 114 | return FakeSupportNMS.createFallingBlock(this) 115 | } 116 | 117 | fun ItemStack.createItemEntity(): Item { 118 | return FakeSupportNMS.createItemEntity(this) 119 | } 120 | 121 | // TODO 아래 함수 두개 리펙토링 해야할듯? 230301 122 | fun PlayerProfile.createPlayerEntity( 123 | name: String = this.name ?: error("PlayerProfile.name is null"), 124 | profileProperties: Set = this.properties, 125 | skinParts: FakeSkinParts = FakeSkinParts().apply { enableAll() }, 126 | uniqueId: UUID = UUID.randomUUID() 127 | ): Player { 128 | return FakeSupportNMS.createPlayerEntity(name, profileProperties, skinParts, uniqueId) 129 | } 130 | 131 | fun createPlayerEntity( 132 | name: String, 133 | profileProperties: Set, 134 | skinParts: FakeSkinParts, 135 | uniqueId: UUID = UUID.randomUUID() 136 | ): Player { 137 | return FakeSupportNMS.createPlayerEntity(name, profileProperties, skinParts, uniqueId) 138 | } 139 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/hash/LongHash.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.hash 19 | 20 | 21 | infix fun Int.pair(least: Int): Long { 22 | return (toLong() and 0xFFFFFFFFL) or ((least.toLong() and 0xFFFFFFFFL) shl 32) 23 | } 24 | 25 | fun Long.mostInt() = (this ushr 32 and 0xFFFFFFFFL).toInt() 26 | 27 | fun Long.leastInt() = (this and 0xFFFFFFFFL).toInt() -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/item/ItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.item 19 | 20 | import io.github.monun.tap.loader.LibraryLoader 21 | import org.bukkit.inventory.EquipmentSlot 22 | import org.bukkit.inventory.ItemStack 23 | import org.bukkit.inventory.PlayerInventory 24 | 25 | interface ItemSupport { 26 | companion object : ItemSupport by LibraryLoader.loadNMS(ItemSupport::class.java) 27 | 28 | fun saveToJsonString(item: ItemStack): String { 29 | error("Unsupported nms version") 30 | } 31 | 32 | fun damageArmor(playerInventory: PlayerInventory, attackDamage: Double) { 33 | error("Unsupported nms version") 34 | } 35 | 36 | fun damageSlot(playerInventory: PlayerInventory, slot: EquipmentSlot, damage: Int) { 37 | error("Unsupported nms version") 38 | } 39 | } 40 | 41 | fun ItemStack.saveToJsonString(): String { 42 | return ItemSupport.saveToJsonString(this) 43 | } 44 | 45 | fun PlayerInventory.damageArmor(attackDamage: Double) { 46 | ItemSupport.damageArmor(this, attackDamage) 47 | } 48 | 49 | fun PlayerInventory.damageSlot(slot: EquipmentSlot, damage: Int = 1) { 50 | ItemSupport.damageSlot(this, slot, damage) 51 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/loader/LibraryLoader.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.loader 19 | 20 | import org.bukkit.Bukkit 21 | import java.lang.reflect.InvocationTargetException 22 | 23 | object LibraryLoader { 24 | 25 | /** 26 | * 구현 라이브러리 인스턴스를 로드합니다 27 | * 28 | * 패키지는 `<[type]의 패키지>.internal.<[type]의 이름>+Impl` 입니다. 29 | * 30 | * ex) `io.github.sample.Sample -> io.github.sample.internal.SampleImpl` 31 | */ 32 | fun loadImplement(type: Class, vararg initArgs: Any? = emptyArray()): T { 33 | val packageName = type.`package`.name 34 | val className = "${type.simpleName}Impl" 35 | val parameterTypes = initArgs.map { it?.javaClass }.toTypedArray() 36 | 37 | return try { 38 | val internalClass = 39 | Class.forName("$packageName.internal.$className", true, type.classLoader).asSubclass(type) 40 | 41 | val constructor = kotlin.runCatching { 42 | internalClass.getConstructor(*parameterTypes) 43 | }.getOrNull() 44 | ?: throw UnsupportedOperationException("${type.name} does not have Constructor for [${parameterTypes.joinToString()}]") 45 | constructor.newInstance(*initArgs) as T 46 | } catch (exception: ClassNotFoundException) { 47 | throw UnsupportedOperationException("${type.name} a does not have implement", exception) 48 | } catch (exception: IllegalAccessException) { 49 | throw UnsupportedOperationException("${type.name} constructor is not visible") 50 | } catch (exception: InstantiationException) { 51 | throw UnsupportedOperationException("${type.name} is abstract class") 52 | } catch (exception: InvocationTargetException) { 53 | throw UnsupportedOperationException( 54 | "${type.name} has an error occurred while creating the instance", 55 | exception 56 | ) 57 | } 58 | } 59 | 60 | /** 61 | * net.minecraft.server 를 지원하는 라이브러리 인스턴스를 로드합니다. 62 | * 63 | * 패키지는 <[type]의 패키지>.[minecraftVersion].NMS + <[type]의 이름> 입니다. 64 | * 65 | * 66 | * ex) `io.github.sample.Sample -> io.github.sample.v1_18_R1.NMSSample` 67 | */ 68 | fun loadNMS(type: Class, vararg initArgs: Any? = emptyArray()): T { 69 | val packageName = type.`package`.name 70 | val className = "NMS${type.simpleName}" 71 | val parameterTypes = initArgs.map { 72 | it?.javaClass 73 | }.toTypedArray() 74 | 75 | val candidates = ArrayList(2) 76 | candidates.add("$packageName.$libraryVersion.$className") 77 | 78 | val lastDot = packageName.lastIndexOf('.') 79 | if (lastDot > 0) { 80 | val superPackageName = packageName.substring(0, lastDot) 81 | val subPackageName = packageName.substring(lastDot + 1) 82 | candidates.add("$superPackageName.$libraryVersion.$subPackageName.$className") 83 | } 84 | 85 | return try { 86 | val nmsClass = candidates.firstNotNullOfOrNull { candidate -> 87 | try { 88 | Class.forName(candidate, true, type.classLoader).asSubclass(type) 89 | } catch (exception: ClassNotFoundException) { 90 | null 91 | } 92 | } ?: throw ClassNotFoundException("Not found nms library class: $candidates") 93 | val constructor = kotlin.runCatching { 94 | nmsClass.getConstructor(*parameterTypes) 95 | }.getOrNull() 96 | ?: throw UnsupportedOperationException("${type.name} does not have Constructor for [${parameterTypes.joinToString()}]") 97 | constructor.newInstance(*initArgs) as T 98 | } catch (exception: ClassNotFoundException) { 99 | throw UnsupportedOperationException( 100 | "${type.name} does not support this version: $libraryVersion", 101 | exception 102 | ) 103 | } catch (exception: IllegalAccessException) { 104 | throw UnsupportedOperationException("${type.name} constructor is not visible") 105 | } catch (exception: InstantiationException) { 106 | throw UnsupportedOperationException("${type.name} is abstract class") 107 | } catch (exception: InvocationTargetException) { 108 | throw UnsupportedOperationException( 109 | "${type.name} has an error occurred while creating the instance", 110 | exception 111 | ) 112 | } 113 | } 114 | 115 | val bukkitVersion by lazy { 116 | Bukkit.getServer().bukkitVersion 117 | } 118 | 119 | val minecraftVersion by lazy { 120 | Bukkit.getServer().minecraftVersion 121 | } 122 | 123 | val libraryVersion by lazy { "v${minecraftVersion.replace('.', '_')}" } 124 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/math/LocationSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.math 19 | 20 | import org.bukkit.Location 21 | import org.bukkit.util.Vector 22 | 23 | fun Location.copyTo(other: Location) { 24 | world = other.world 25 | set(other.x, other.y, other.z) 26 | yaw = other.yaw 27 | pitch = other.pitch 28 | } 29 | 30 | infix fun Location.vector(target: Location): Vector { 31 | return Vector(target.x - x, target.y - y, target.z - z) 32 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/math/MathSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.math 19 | 20 | fun Double.toRadians(): Double { 21 | return Math.toRadians(this) 22 | } 23 | 24 | fun Double.toDegrees(): Double { 25 | return Math.toDegrees(this) 26 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/math/VectorSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.math 19 | 20 | import org.bukkit.util.Vector 21 | import kotlin.math.cos 22 | import kotlin.math.sin 23 | 24 | /** 25 | * @author Noonmaru 26 | */ 27 | fun Iterable.rotateAroundX(angle: Double) { 28 | val angleCos = cos(angle) 29 | val angleSin = sin(angle) 30 | 31 | forEach { 32 | val y = angleCos * it.y - angleSin * it.z 33 | val z = angleSin * it.y + angleCos * it.z 34 | it.y = y 35 | it.z = z 36 | } 37 | } 38 | 39 | fun Iterable.rotateAroundY(angle: Double) { 40 | val angleCos = cos(angle) 41 | val angleSin = sin(angle) 42 | 43 | forEach { 44 | val x = angleCos * it.x + angleSin * it.z 45 | val z = -angleSin * it.x + angleCos * it.z 46 | it.x = x 47 | it.z = z 48 | } 49 | } 50 | 51 | fun Iterable.rotateAroundZ(angle: Double) { 52 | val angleCos = cos(angle) 53 | val angleSin = sin(angle) 54 | 55 | forEach { 56 | val x = angleCos * it.x - angleSin * it.y 57 | val y = angleSin * it.x + angleCos * it.y 58 | it.x = x 59 | it.y = y 60 | } 61 | } 62 | 63 | fun Vector.divide(d: Double) { 64 | x /= d 65 | y /= d 66 | z /= d 67 | } 68 | 69 | fun Vector.normalizeAndLength(): Double { 70 | val length = length() 71 | 72 | x /= length 73 | y /= length 74 | z /= length 75 | 76 | return length 77 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/math/WorldSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.math 19 | 20 | import org.bukkit.util.NumberConversions 21 | 22 | fun Int.toSection() = this shr 4 23 | 24 | fun Double.toSection() = NumberConversions.floor(this) shr 4 -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/mojangapi/MojangAPI.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.mojangapi 19 | 20 | import com.destroystokyo.paper.profile.ProfileProperty 21 | import kotlinx.serialization.Serializable 22 | import kotlinx.serialization.decodeFromString 23 | import kotlinx.serialization.json.Json 24 | import java.math.BigInteger 25 | import java.net.URI 26 | import java.net.http.HttpClient 27 | import java.net.http.HttpRequest 28 | import java.net.http.HttpResponse 29 | import java.util.* 30 | import java.util.concurrent.CompletableFuture 31 | 32 | /** 33 | * https://wiki.vg/Mojang_API 34 | */ 35 | object MojangAPI { 36 | 37 | @Serializable 38 | data class Profile( 39 | val name: String, 40 | val id: String 41 | ) { 42 | fun uuid(): UUID = BigInteger(id, 16).let { bigInteger -> 43 | return UUID(bigInteger.shiftRight(64).toLong(), bigInteger.toLong()) 44 | } 45 | } 46 | 47 | private inline fun fetchAsync(url: String): CompletableFuture { 48 | val client = HttpClient.newHttpClient() 49 | val request = HttpRequest.newBuilder(URI.create(url)) 50 | .GET() 51 | .build() 52 | 53 | return client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply { response -> 54 | val body = response.body() 55 | if (body.isBlank()) null else Json { ignoreUnknownKeys = true }.decodeFromString(body) 56 | } 57 | } 58 | 59 | fun fetchProfileAsync(username: String) = 60 | fetchAsync("https://api.mojang.com/users/profiles/minecraft/$username") 61 | 62 | fun fetchProfile(username: String) = fetchProfileAsync(username).get() 63 | 64 | @Serializable 65 | data class SkinProfile( 66 | val id: String, 67 | val name: String, 68 | val properties: List 69 | ) { 70 | fun textureProfile() = properties.find { it.name == "textures" }?.let { textures -> 71 | val string = Base64.getDecoder().decode(textures.value).decodeToString() 72 | Json { ignoreUnknownKeys = true }.decodeFromString(string) 73 | } 74 | 75 | fun profileProperties() = properties.map { it.profileProperty() } 76 | } 77 | 78 | @Serializable 79 | data class Property( 80 | val name: String, 81 | val value: String, 82 | val signature: String? = null 83 | ) { 84 | fun profileProperty() = ProfileProperty(name, value, signature) 85 | } 86 | 87 | @Serializable 88 | data class TextureProfile( 89 | val timestamp: Long, 90 | val profileId: String, 91 | val profileName: String, 92 | val signatureRequired: Boolean, 93 | val textures: Textures 94 | ) 95 | 96 | @Serializable 97 | data class Textures( 98 | val SKIN: TextureSkin, 99 | val CAPE: TextureCape? = null 100 | ) 101 | 102 | @Serializable 103 | data class TextureSkin(val url: String, val metadata: TextureMetadata? = null) 104 | 105 | @Serializable 106 | data class TextureMetadata(val model: String) 107 | 108 | @Serializable 109 | data class TextureCape(val url: String) 110 | 111 | fun fetchSkinProfileAsync(trimmedUUID: String) = 112 | fetchAsync("https://sessionserver.mojang.com/session/minecraft/profile/$trimmedUUID?unsigned=false") 113 | 114 | fun fetchSkinProfile(trimmedUUID: String) = fetchSkinProfileAsync(trimmedUUID).get() 115 | 116 | fun fetchSkinProfileAsync(uuid: UUID) = fetchSkinProfileAsync(uuid.toString().replace("-", "")) 117 | 118 | fun fetchSkinProfile(uuid: UUID) = fetchSkinProfileAsync(uuid.toString().replace("-", "")).get() 119 | } 120 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/protocol/AnimationType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.protocol 19 | 20 | enum class AnimationType { 21 | SWING_MAIN_ARM, 22 | TAKE_DAMAGE, 23 | LEAVE_BED, 24 | SWING_OFFHAND, 25 | CRITICAL_EFFECT, 26 | MAGIC_CRITICAL_EFFECT 27 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/protocol/PacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.protocol 19 | 20 | import org.bukkit.Location 21 | import org.bukkit.Server 22 | import org.bukkit.World 23 | import org.bukkit.entity.Player 24 | import org.bukkit.util.BoundingBox 25 | 26 | @Suppress("NOTHING_TO_INLINE") 27 | private inline fun Double.square() = this * this 28 | 29 | interface PacketContainer { 30 | fun sendTo(player: Player) 31 | } 32 | 33 | fun Player.sendPacket(packet: PacketContainer) = packet.sendTo(this) 34 | 35 | fun World.sendPacket(packet: PacketContainer) = players.forEach { packet.sendTo(it) } 36 | 37 | fun World.sendPacketNearBy( 38 | box: BoundingBox, 39 | packet: PacketContainer, 40 | predicate: ((player: Player) -> Boolean)? = null 41 | ) { 42 | players.asSequence().filter { 43 | val loc = it.location 44 | box.contains(loc.x, loc.y, loc.z) 45 | }.let { players -> 46 | if (predicate == null) players else players.filter(predicate) 47 | }.forEach { 48 | packet.sendTo(it) 49 | } 50 | } 51 | 52 | fun World.sendPacketNearBy( 53 | x: Double, 54 | y: Double, 55 | z: Double, 56 | xRadius: Double, 57 | yRadius: Double, 58 | zRadius: Double, 59 | packet: PacketContainer, 60 | predicate: ((player: Player) -> Boolean)? = null 61 | ) = sendPacketNearBy( 62 | BoundingBox( 63 | x - xRadius, y - yRadius, z - zRadius, 64 | x + xRadius, y + yRadius, z + zRadius 65 | ), packet, predicate 66 | ) 67 | 68 | fun World.sendPacketNearBy( 69 | x: Double, 70 | y: Double, 71 | z: Double, 72 | xzRadius: Double, 73 | yRadius: Double, 74 | packet: PacketContainer, 75 | predicate: ((player: Player) -> Boolean)? = null 76 | ) = sendPacketNearBy( 77 | BoundingBox( 78 | x - xzRadius, y - yRadius, z - xzRadius, 79 | x + xzRadius, y + yRadius, z + xzRadius 80 | ), packet, predicate 81 | ) 82 | 83 | fun World.sendPacketNearBy( 84 | loc: Location, 85 | xRadius: Double, 86 | yRadius: Double, 87 | zRadius: Double, 88 | packet: PacketContainer, 89 | predicate: ((player: Player) -> Boolean)? = null 90 | ) = sendPacketNearBy(loc.x, loc.y, loc.z, xRadius, yRadius, zRadius, packet, predicate) 91 | 92 | fun World.sendPacketNearBy( 93 | loc: Location, 94 | xzRadius: Double, 95 | yRadius: Double, 96 | packet: PacketContainer, 97 | predicate: ((player: Player) -> Boolean)? = null 98 | ) = sendPacketNearBy(loc.x, loc.y, loc.z, xzRadius, yRadius, packet, predicate) 99 | 100 | fun Server.sendPacket( 101 | packet: PacketContainer, 102 | predicate: ((player: Player) -> Boolean)? = null 103 | ) = onlinePlayers.asSequence().let { 104 | if (predicate == null) it else it.filter(predicate) 105 | }.forEach { packet.sendTo(it) } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/protocol/PlayerInfoAction.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.protocol 19 | 20 | /** 21 | * @author octomarine 22 | */ 23 | enum class PlayerInfoAction { 24 | ADD, 25 | GAME_MODE, 26 | LATENCY, 27 | DISPLAY_NAME, 28 | @Deprecated("Removed in 1.19.3") 29 | REMOVE 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/protocol/PlayerInfoUpdateAction.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.protocol 19 | 20 | enum class PlayerInfoUpdateAction { 21 | ADD_PLAYER, 22 | INITIALIZE_CHAT, 23 | UPDATE_GAME_MODE, 24 | UPDATE_LISTED, 25 | UPDATE_LATENCY, 26 | UPDATE_DISPLAY_NAME 27 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/ref/Weaky.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.ref 19 | 20 | import org.jetbrains.annotations.NotNull 21 | import java.lang.ref.ReferenceQueue 22 | import java.lang.ref.WeakReference 23 | import kotlin.reflect.KProperty 24 | 25 | /** 26 | * WeakReference를 Delegate로 사용하기 위한 클래스입니다. 27 | * 28 | * [weaky] 함수로 간단하게 이용하세요. 29 | */ 30 | class Weaky : WeakReference { 31 | internal constructor(referent: T) : super(referent) 32 | internal constructor( 33 | referent: T, q: ReferenceQueue 34 | ) : super(referent, q) 35 | 36 | @NotNull 37 | override fun get(): T { 38 | return super.get() 39 | ?: throw IllegalStateException("Cannot get reference as it has already been Garbage Collected") 40 | } 41 | 42 | override fun hashCode(): Int { 43 | return get().hashCode() 44 | } 45 | 46 | override fun equals(other: Any?): Boolean { 47 | return get() == other 48 | } 49 | 50 | override fun toString(): String { 51 | return get().toString() 52 | } 53 | } 54 | 55 | fun weaky(referent: T) = Weaky(referent) 56 | 57 | fun weaky(referent: T, queue: ReferenceQueue) = Weaky(referent, queue) 58 | 59 | operator fun Weaky.getValue(thisRef: Any?, property: KProperty<*>): T { 60 | return get() 61 | } 62 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/task/Ticker.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.task 19 | 20 | import java.util.* 21 | import kotlin.math.max 22 | 23 | /** 24 | * Tick 기반의 태스크 스케쥴러 (Tick + Timer = Ticker) 25 | * 26 | * @see TickerTask 27 | */ 28 | abstract class Ticker : Runnable { 29 | companion object { 30 | /** 31 | * 호출 횟수에 따라 tick이 증가하는 Ticker를 생성합니다. 32 | */ 33 | fun plank(): Ticker { 34 | return Plank() 35 | } 36 | 37 | /** 38 | * 시간에 따라 tick이 변화하는 Ticker를 생성합니다. 39 | * 40 | * 태스크는 시간 지연 관계없이 tick과 동기화되어 실행됩니다. 41 | */ 42 | fun precision(tick: Pair<() -> Long, Long> = System::nanoTime to 50L * 1000L * 1000L): Ticker { 43 | return Precision(tick.first, tick.second) 44 | } 45 | 46 | /** 47 | * 시간에 따라 tick이 변화하는 Ticker를 생성합니다. 48 | * 49 | * 태스크는 시간 지연에 따라 한번만 호출됩니다. 50 | */ 51 | fun flex(tick: Pair<() -> Long, Long> = System::nanoTime to 50L * 1000L * 1000L): Ticker { 52 | return Flex(tick.first, tick.second) 53 | } 54 | } 55 | 56 | /** 57 | * Ticker 내부에서 사용하는 tick입니다. 58 | */ 59 | abstract val currentTicks: Long 60 | 61 | protected val queue = PriorityQueue() 62 | 63 | var removeDelay = 0xFF 64 | 65 | protected open fun TickerTask.calculateNextRun() = nextRun + period 66 | 67 | /** 68 | * 지연 실행할 태스크를 등록합니다. 69 | * 70 | * 태스크는 한번만 호출된 이후 [TickerTask.isDone] 상태가 됩니다. 71 | */ 72 | fun runTask(runnable: Runnable, delay: Long = 0L) = registerTask(runnable, delay, TickerTask.NO_REPEATING) 73 | 74 | /** 75 | * 반복 실행할 태스크를 등록합니다. 76 | * 77 | * 태스크는 지연 이후에 period tick 마다 호출됩니다. 78 | */ 79 | fun runTaskTimer(runnable: Runnable, delay: Long, period: Long) = registerTask(runnable, delay, max(1L, period)) 80 | 81 | private fun registerTask(runnable: Runnable, delay: Long, period: Long) = TickerTask(this, runnable).apply { 82 | this.nextRun = currentTicks + max(0L, delay) 83 | this.period = period 84 | }.also(queue::offer) 85 | 86 | /** 87 | * 모든 태스크를 실행합니다. 88 | */ 89 | override fun run() { 90 | val queue = queue 91 | while (queue.peek().let { it != null && it.nextRun <= currentTicks }) { 92 | val task = queue.remove() 93 | 94 | if (task.isScheduled) task.run { 95 | execute() 96 | 97 | if (period > 0L) { 98 | nextRun = task.calculateNextRun() 99 | queue.offer(task) 100 | } else { 101 | period = TickerTask.DONE 102 | } 103 | } 104 | } 105 | } 106 | 107 | internal fun remove(task: TickerTask) { 108 | queue.remove(task) 109 | } 110 | 111 | fun cancelAll() { 112 | queue.apply { 113 | forEach { it.period = TickerTask.CANCEL } 114 | clear() 115 | } 116 | } 117 | 118 | private class Plank : Ticker() { 119 | override var currentTicks = 0L 120 | 121 | override fun run() { 122 | super.run() 123 | currentTicks++ 124 | } 125 | } 126 | 127 | private class Precision( 128 | private val time: () -> Long, 129 | private val tickTime: Long 130 | ) : Ticker() { 131 | private val currentTicksByTime = time() 132 | get() = (time() - field) / tickTime 133 | 134 | override var currentTicks = 0L 135 | 136 | override fun run() { 137 | super.run() 138 | 139 | while (currentTicks < currentTicksByTime) { 140 | if (queue.isEmpty()) { 141 | currentTicks = currentTicksByTime 142 | return 143 | } 144 | currentTicks++ 145 | super.run() 146 | } 147 | } 148 | } 149 | 150 | private class Flex( 151 | private val time: () -> Long, 152 | private val tickTime: Long 153 | ) : Ticker() { 154 | override val currentTicks = time() 155 | get() = (time() - field) / tickTime 156 | 157 | override fun TickerTask.calculateNextRun() = currentTicks + period 158 | } 159 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/task/TickerTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.task 19 | 20 | import io.github.monun.tap.ref.Weaky 21 | 22 | /** 23 | * Ticker에 등록된 태스크입니다. 24 | * 25 | * @see Ticker 26 | */ 27 | class TickerTask internal constructor( 28 | ticker: Ticker, 29 | val runnable: Runnable 30 | ) : Comparable { 31 | companion object { 32 | internal const val ERROR = 0L 33 | internal const val NO_REPEATING = -1L 34 | internal const val CANCEL = -2L 35 | internal const val DONE = -3L 36 | } 37 | 38 | private val schedulerRef = Weaky(ticker) 39 | 40 | /** 41 | * 태스크를 등록한 Ticker 객체입니다 42 | */ 43 | val ticker: Ticker 44 | get() = schedulerRef.get() 45 | 46 | internal var nextRun: Long = -1L 47 | 48 | /** 49 | * 태스크 등록시 설정한 반복 tick입니다 50 | */ 51 | var period: Long = 0L 52 | internal set 53 | 54 | /** 55 | * 등록된 태스크 56 | */ 57 | val isScheduled: Boolean 58 | get() = period.let { it != ERROR && it > CANCEL } 59 | 60 | /** 61 | * 취소된 태스크 62 | */ 63 | val isCancelled 64 | get() = period == CANCEL 65 | 66 | /** 67 | * 실행이 완료된 태스크 68 | */ 69 | val isDone 70 | get() = period == DONE 71 | 72 | internal fun execute() { 73 | runnable.runCatching { run() } 74 | } 75 | 76 | /** 77 | * 태스크를 해제합니다. 78 | * 79 | * 등록되지 태스크의 경우 아무것도 실행하지 않습니다. 80 | */ 81 | fun cancel() { 82 | if (!isScheduled) return 83 | period = CANCEL 84 | 85 | // 실행까지 남은 틱이 Ticker의 removeDelay 값보다 이상일때 즉시 제거 86 | // 아닐경우 tick 흐름에 따라 자연스럽게 제거 87 | val ticker = ticker 88 | if (nextRun - ticker.currentTicks >= ticker.removeDelay) 89 | ticker.remove(this) 90 | } 91 | 92 | override fun compareTo(other: TickerTask): Int { 93 | return this.nextRun.compareTo(other.nextRun) 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/template/ComponentSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.template 19 | 20 | import net.kyori.adventure.text.BuildableComponent 21 | import net.kyori.adventure.text.Component 22 | import net.kyori.adventure.text.ComponentBuilder 23 | import net.kyori.adventure.text.TextComponent 24 | import org.bukkit.configuration.ConfigurationSection 25 | 26 | fun > T.renderTemplates(config: ConfigurationSection): T { 27 | applyDeep { 28 | if (it is TextComponent.Builder) 29 | it.content(it.content().renderTemplates(config)) 30 | } 31 | 32 | return this 33 | } 34 | 35 | @Suppress("UNCHECKED_CAST") 36 | fun T.renderTemplates(config: ConfigurationSection) = if (this is BuildableComponent<*, *>) { 37 | toBuilder().renderTemplates(config).build() as T 38 | } else { 39 | this 40 | } 41 | 42 | 43 | @JvmName("renderComponentBuilderTemplatesAll") 44 | fun > Iterable.renderTemplatesAll(config: ConfigurationSection) = 45 | forEach { it.renderTemplates(config) } 46 | 47 | @JvmName("renderComponentTemplatesAll") 48 | fun Iterable.renderTemplatesAll(config: ConfigurationSection): List = map { 49 | it.renderTemplates(config) 50 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/trail/TrailSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.trail 19 | 20 | import io.github.monun.tap.math.normalizeAndLength 21 | import org.bukkit.Location 22 | import org.bukkit.World 23 | import org.bukkit.util.Vector 24 | import kotlin.math.max 25 | 26 | /** 27 | * 궤적 계산 지원 28 | */ 29 | object TrailSupport { 30 | /** 31 | * 궤적을 계산합니다. 32 | * @param start 시작 위치 33 | * @param vector 방향 벡터 (정규화 필요 없음) 34 | * @param interval 지점간 간격 35 | * @param trailer 지점 소비 함수 36 | */ 37 | fun trail( 38 | start: Location, 39 | vector: Vector, 40 | interval: Double, 41 | trailer: (world: World, x: Double, y: Double, z: Double) -> Unit 42 | ) { 43 | val length = vector.normalizeAndLength() 44 | val count = max(1, (length / interval).toInt()) 45 | val world = start.world 46 | val x = start.x 47 | val y = start.y 48 | val z = start.z 49 | val deltaX = vector.x * interval 50 | val deltaY = vector.y * interval 51 | val deltaZ = vector.z * interval 52 | 53 | for (i in 0 until count) { 54 | trailer( 55 | world, 56 | x + deltaX * i, 57 | y + deltaY * i, 58 | z + deltaZ * i 59 | ) 60 | } 61 | } 62 | 63 | /** 64 | * 궤적을 계산합니다. 65 | * @param start 시작 위치 66 | * @param end 마지막 위치 67 | * @param interval 지점간 간격 68 | * @param trailer 지점 소비 함수 69 | */ 70 | fun trail( 71 | start: Location, 72 | end: Location, 73 | interval: Double, 74 | trailer: (world: World, x: Double, y: Double, z: Double) -> Unit 75 | ) { 76 | require(start.world === end.world) { "Differing worlds" } 77 | 78 | trail(start, Vector(end.x - start.x, end.y - start.y, end.z - start.z), interval, trailer) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/util/AlphanumComparator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.util 19 | 20 | /** 21 | * This is an updated version with enhancements made by Daniel Migowski, 22 | * Andre Bogus, and David Koelle. Updated by David Koelle in 2017. 23 | * 24 | * To use this class: 25 | * Use the static "sort" method from the java.util.Collections class: 26 | * Collections.sort(your list, new AlphanumComparator()); 27 | */ 28 | object AlphanumComparator : Comparator { 29 | private fun isDigit(ch: Char): Boolean { 30 | return ch.code in 48..57 31 | } 32 | 33 | /** Length of string is passed in for improved efficiency (only need to calculate it once) */ 34 | private fun getChunk(s: String, slength: Int, marker: Int): String { 35 | var m = marker 36 | val chunk = StringBuilder() 37 | var c = s[m] 38 | chunk.append(c) 39 | m++ 40 | if (isDigit(c)) { 41 | while (m < slength) { 42 | c = s[m] 43 | if (!isDigit(c)) break 44 | chunk.append(c) 45 | m++ 46 | } 47 | } else { 48 | while (m < slength) { 49 | c = s[m] 50 | if (isDigit(c)) break 51 | chunk.append(c) 52 | m++ 53 | } 54 | } 55 | return chunk.toString() 56 | } 57 | 58 | override fun compare(s1: String?, s2: String?): Int { 59 | if (s1 == null || s2 == null) { 60 | return 0 61 | } 62 | var thisMarker = 0 63 | var thatMarker = 0 64 | val s1Length = s1.length 65 | val s2Length = s2.length 66 | while (thisMarker < s1Length && thatMarker < s2Length) { 67 | val thisChunk = getChunk(s1, s1Length, thisMarker) 68 | thisMarker += thisChunk.length 69 | val thatChunk = getChunk(s2, s2Length, thatMarker) 70 | thatMarker += thatChunk.length 71 | 72 | // If both chunks contain numeric characters, sort them numerically 73 | var result: Int 74 | if (isDigit(thisChunk[0]) && isDigit(thatChunk[0])) { 75 | // Simple chunk comparison by length. 76 | val thisChunkLength = thisChunk.length 77 | result = thisChunkLength - thatChunk.length 78 | // If equal, the first different number counts 79 | if (result == 0) { 80 | for (i in 0 until thisChunkLength) { 81 | result = thisChunk[i] - thatChunk[i] 82 | if (result != 0) { 83 | return result 84 | } 85 | } 86 | } 87 | } else { 88 | result = thisChunk.compareTo(thatChunk) 89 | } 90 | if (result != 0) return result 91 | } 92 | return s1Length - s2Length 93 | } 94 | } -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/util/GameModeSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.util 19 | 20 | import org.bukkit.GameMode 21 | 22 | val GameMode.isDamageable 23 | get() = this == GameMode.SURVIVAL || this == GameMode.ADVENTURE -------------------------------------------------------------------------------- /tap-api/src/main/kotlin/io/github/monun/tap/util/VersionSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.util 19 | 20 | import kotlin.math.max 21 | 22 | /** 23 | * 버전을 비교합니다. 24 | * 25 | * 0.1 < 0.1.1 26 | * 27 | * 0.1 == 0.01 28 | * 29 | * 0.1-beta < 0.1-release 30 | * 31 | * 0.1-final < 0.1 32 | * 33 | */ 34 | 35 | enum class MavenVersionIdentifier(val priority: Int) { 36 | NONE(10), 37 | RELEASE(9), 38 | GA(8), 39 | FINAL(7), 40 | SNAPSHOT(6), 41 | RC(5), 42 | ZETA(4), 43 | BETA(3), 44 | ALPHA(2), 45 | DEV(1) 46 | } 47 | 48 | private val String.identifier: MavenVersionIdentifier 49 | get() { 50 | return if (equals("0")) { 51 | MavenVersionIdentifier.NONE 52 | } else { 53 | try { 54 | MavenVersionIdentifier.valueOf(uppercase()) 55 | } catch (e: IllegalArgumentException) { 56 | throw RuntimeException("No such version identifier found: $this") 57 | } 58 | } 59 | } 60 | 61 | private val String.isValidLong: Boolean 62 | get() { 63 | return try { 64 | toLong(0x10) 65 | true 66 | } catch (e: NumberFormatException) { 67 | false 68 | } 69 | } 70 | 71 | infix fun String.compareVersion(other: String): Int { 72 | if (!matches("""^\d+(\.\d+)*(-[a-zA-Z]*)?$""".toRegex()) || !other.matches("""^\d+(\.\d+)*(-[a-zA-Z]*)?$""".toRegex())) { 73 | throw RuntimeException("The version format does not valid.") 74 | } 75 | val split = replace("-", ".").split('.') 76 | val otherSplit = other.replace("-", ".").split('.') 77 | 78 | loop@ for (i in 0 until max(split.count(), otherSplit.count())) { 79 | val a = split.getOrNull(i) ?: "0" 80 | val b = otherSplit.getOrNull(i) ?: "0" 81 | var compare = 0 82 | val isLastInIndex = i == max(split.count(), otherSplit.count()) - 1 83 | 84 | kotlin.runCatching { 85 | compare = if (isLastInIndex && (!a.isValidLong || !b.isValidLong)) { 86 | a.identifier.priority.compareTo(b.identifier.priority) 87 | } else { 88 | a.toLong(0x10).compareTo(b.toLong(0x10)) 89 | } 90 | }.onFailure { 91 | compare = AlphanumComparator.compare(a, b) 92 | } 93 | if (compare != 0) return compare 94 | } 95 | 96 | return 0 97 | } 98 | -------------------------------------------------------------------------------- /tap-api/src/test/kotlin/io/github/monun/tap/mojangapi/MojangAPITest.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.mojangapi 2 | 3 | import org.junit.jupiter.api.Assertions.assertEquals 4 | import org.junit.jupiter.api.Assertions.assertNotNull 5 | import org.junit.jupiter.api.Test 6 | 7 | 8 | class MojangAPITest { 9 | @Test 10 | fun testUsernameToUUID() { 11 | val profile = MojangAPI.fetchProfile("jeb_")!! 12 | assertEquals("jeb_", profile.name) 13 | assertEquals("853c80ef3c3749fdaa49938b674adae6", profile.id) 14 | assertNotNull(MojangAPI.fetchSkinProfile(profile.id)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tap-core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api(projectApi) 3 | } 4 | 5 | tasks { 6 | jar { 7 | archiveClassifier.set("origin") 8 | } 9 | 10 | register("coreDevJar") { 11 | from(sourceSets["main"].output) 12 | } 13 | 14 | register("coreReobfJar") { 15 | from(sourceSets["main"].output) 16 | } 17 | } -------------------------------------------------------------------------------- /tap-core/src/main/kotlin/io/github/monun/tap/fake/internal/FakeInternalImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake.internal 19 | 20 | import io.github.monun.tap.fake.FakeEntityServer 21 | import io.github.monun.tap.fake.FakeInternal 22 | import org.bukkit.plugin.java.JavaPlugin 23 | 24 | class FakeInternalImpl : FakeInternal { 25 | override fun create(plugin: JavaPlugin): FakeEntityServer { 26 | return FakeEntityServerImpl(plugin) 27 | } 28 | } -------------------------------------------------------------------------------- /tap-core/src/main/kotlin/io/github/monun/tap/fake/internal/FakeTracker.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.fake.internal 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import io.github.monun.tap.protocol.sendPacket 22 | import io.github.monun.tap.ref.getValue 23 | import io.github.monun.tap.ref.weaky 24 | import org.bukkit.entity.Player 25 | 26 | internal class FakeTracker( 27 | server: FakeEntityServerImpl, 28 | val player: Player 29 | ) { 30 | private val server by weaky(server) 31 | 32 | internal var location = player.location 33 | private set 34 | 35 | internal var valid = player.isOnline 36 | 37 | private val trackingEntities = HashSet>() 38 | 39 | fun update() { 40 | if (!valid) { 41 | if (player.isValid) { 42 | valid = true 43 | this.location = player.location 44 | broadcastSelf() 45 | return 46 | } 47 | } 48 | 49 | val prevLocation = this.location 50 | val currentLocation = player.location 51 | this.location = currentLocation 52 | 53 | if (prevLocation.world !== currentLocation.world 54 | || prevLocation.x != currentLocation.x 55 | || prevLocation.y != currentLocation.y 56 | || prevLocation.z != currentLocation.z 57 | ) { 58 | broadcastSelf() 59 | } 60 | } 61 | 62 | internal fun clear() { 63 | valid = false 64 | 65 | val player = player 66 | 67 | trackingEntities.apply { 68 | for (entity in this) { 69 | entity.removeTracker(this@FakeTracker) 70 | entity.despawnTo(player) 71 | } 72 | 73 | clear() 74 | } 75 | } 76 | 77 | internal fun broadcastSelf() { 78 | for (entity in server._entities) { 79 | entity.offerComputeQueue(this) 80 | } 81 | } 82 | 83 | internal fun removeEntity(entity: FakeEntityImpl<*>) { 84 | this.trackingEntities -= entity 85 | } 86 | 87 | internal fun addEntity(entity: FakeEntityImpl<*>) { 88 | this.trackingEntities += entity 89 | } 90 | 91 | internal fun clearEntities() { 92 | trackingEntities.clear() 93 | } 94 | 95 | internal fun destroy() { 96 | val player = player 97 | 98 | for (entity in trackingEntities) { 99 | entity.removeTracker(this@FakeTracker) 100 | entity.despawnTo(player) 101 | } 102 | clearEntities() 103 | valid = false 104 | } 105 | } 106 | 107 | internal fun Iterable.sendServerPacketAll(packet: PacketContainer) { 108 | for (tracker in this) { 109 | tracker.player.sendPacket(packet) 110 | } 111 | } -------------------------------------------------------------------------------- /tap-dongle/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import io.papermc.paperweight.tasks.RemapJar 2 | 3 | plugins { 4 | id("io.papermc.paperweight.userdev") version "1.5.5" apply false 5 | } 6 | 7 | subprojects { 8 | // net.minecraft.server 프로젝트의 이름은 반드시 v로 시작 [v1.19] 9 | apply(plugin = "io.papermc.paperweight.userdev") 10 | dependencies { 11 | implementation(projectApi) 12 | implementation(projectCore) 13 | val paperweight = (this as ExtensionAware).extensions.getByName("paperweight") 14 | as io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension 15 | paperweight.paperDevBundle("${name.substring(1)}-R0.1-SNAPSHOT") 16 | } 17 | } 18 | 19 | // upstream 20 | coreDevJar { 21 | from(subprojects.map { it.sourceSets["main"].output }) 22 | } 23 | 24 | coreReobfJar { 25 | subprojects.map { it.tasks.named("reobfJar").get() as RemapJar }.onEach { 26 | from(zipTree(it.outputJar)) 27 | }.let { 28 | dependsOn(it) 29 | } 30 | } 31 | 32 | coreSourcesJar { 33 | from(subprojects.map { it.sourceSets["main"].allSource }) 34 | } 35 | -------------------------------------------------------------------------------- /tap-dongle/v1.18.1/src/main/kotlin/io/github/monun/tap/v1_18_1/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_1.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_18_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18.1/src/main/kotlin/io/github/monun/tap/v1_18_1/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_1.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_18_R1.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18.1/src/main/kotlin/io/github/monun/tap/v1_18_1/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_1.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18.2/src/main/kotlin/io/github/monun/tap/v1_18_2/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_2.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_18_R2.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18.2/src/main/kotlin/io/github/monun/tap/v1_18_2/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_2.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_18_R2.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18.2/src/main/kotlin/io/github/monun/tap/v1_18_2/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18_2.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18/src/main/kotlin/io/github/monun/tap/v1_18/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_18_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18/src/main/kotlin/io/github/monun/tap/v1_18/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_18_R1.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.18/src/main/kotlin/io/github/monun/tap/v1_18/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_18.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.1/src/main/kotlin/io/github/monun/tap/v1_19_1/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_1.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_19_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.1/src/main/kotlin/io/github/monun/tap/v1_19_1/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_1.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.1/src/main/kotlin/io/github/monun/tap/v1_19_1/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_1.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.2/src/main/kotlin/io/github/monun/tap/v1_19_2/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_2.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_19_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.2/src/main/kotlin/io/github/monun/tap/v1_19_2/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_2.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.2/src/main/kotlin/io/github/monun/tap/v1_19_2/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_2.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.3/src/main/kotlin/io/github/monun/tap/v1_19_3/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_3.fake 19 | 20 | import net.minecraft.core.registries.BuiltInRegistries 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_19_R2.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | BuiltInRegistries.ENTITY_TYPE.forEach { type -> 38 | type.create(level)?.let { entity -> 39 | val bukkitClass = entity.bukkitEntity.javaClass 40 | val interfaces = bukkitClass.interfaces 41 | 42 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 43 | 44 | for (i in interfaces) { 45 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 46 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | @JvmStatic 54 | fun findType(bukkitClass: Class): EntityType<*> { 55 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 56 | } 57 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.3/src/main/kotlin/io/github/monun/tap/v1_19_3/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_3.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_19_R2.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.3/src/main/kotlin/io/github/monun/tap/v1_19_3/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_3.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.4/src/main/kotlin/io/github/monun/tap/v1_19_4/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_4.fake 19 | 20 | import net.minecraft.core.registries.BuiltInRegistries 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_19_R3.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | BuiltInRegistries.ENTITY_TYPE.forEach { type -> 38 | type.create(level)?.let { entity -> 39 | val bukkitClass = entity.bukkitEntity.javaClass 40 | val interfaces = bukkitClass.interfaces 41 | 42 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 43 | 44 | for (i in interfaces) { 45 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 46 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | @JvmStatic 54 | fun findType(bukkitClass: Class): EntityType<*> { 55 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 56 | } 57 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.4/src/main/kotlin/io/github/monun/tap/v1_19_4/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_4.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.entity.player.Inventory 23 | import net.minecraft.world.item.ItemStack 24 | import org.bukkit.craftbukkit.v1_19_R3.CraftEquipmentSlot 25 | import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer 26 | import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftInventoryPlayer 27 | import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack 28 | import org.bukkit.inventory.EquipmentSlot 29 | import org.bukkit.inventory.ItemStack as BukkitItemStack 30 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 31 | 32 | class NMSItemSupport : ItemSupport { 33 | override fun saveToJsonString(item: BukkitItemStack): String { 34 | val nmsItem = CraftItemStack.asNMSCopy(item) 35 | return nmsItem.save(CompoundTag()).toString() 36 | } 37 | 38 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 39 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 40 | 41 | nmsInventory.hurtArmor( 42 | nmsInventory.player.damageSources().lava(), 43 | attackDamage.toFloat(), 44 | Inventory.ALL_ARMOR_SLOTS 45 | ) 46 | } 47 | 48 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 49 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 50 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 51 | val nmsItem = nmsInventory.getItem(slot) 52 | 53 | if (!nmsItem.isEmpty) { 54 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 55 | player.broadcastBreakEvent(nmsSlot) 56 | } 57 | } 58 | } 59 | } 60 | 61 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 62 | return when (slot) { 63 | EquipmentSlot.HAND -> getSelected() 64 | EquipmentSlot.OFF_HAND -> offhand[0] 65 | EquipmentSlot.FEET -> armorContents[0] 66 | EquipmentSlot.LEGS -> armorContents[1] 67 | EquipmentSlot.CHEST -> armorContents[2] 68 | EquipmentSlot.HEAD -> armorContents[3] 69 | } 70 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19.4/src/main/kotlin/io/github/monun/tap/v1_19_4/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19_4.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19/src/main/kotlin/io/github/monun/tap/v1_19/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19.fake 19 | 20 | import net.minecraft.core.Registry 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_19_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | 38 | Registry.ENTITY_TYPE.forEach { type -> 39 | type.create(level)?.let { entity -> 40 | val bukkitClass = entity.bukkitEntity.javaClass 41 | val interfaces = bukkitClass.interfaces 42 | 43 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 44 | 45 | for (i in interfaces) { 46 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 47 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @JvmStatic 55 | fun findType(bukkitClass: Class): EntityType<*> { 56 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 57 | } 58 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19/src/main/kotlin/io/github/monun/tap/v1_19/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.damagesource.DamageSource 23 | import net.minecraft.world.entity.player.Inventory 24 | import net.minecraft.world.item.ItemStack 25 | import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot 26 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 27 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryPlayer 28 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack 29 | import org.bukkit.inventory.EquipmentSlot 30 | import org.bukkit.inventory.ItemStack as BukkitItemStack 31 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 32 | 33 | class NMSItemSupport : ItemSupport { 34 | override fun saveToJsonString(item: BukkitItemStack): String { 35 | val nmsItem = CraftItemStack.asNMSCopy(item) 36 | return nmsItem.save(CompoundTag()).toString() 37 | } 38 | 39 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 40 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 41 | 42 | nmsInventory.hurtArmor(DamageSource.LAVA, attackDamage.toFloat(), Inventory.ALL_ARMOR_SLOTS) 43 | } 44 | 45 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 46 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 47 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 48 | val nmsItem = nmsInventory.getItem(slot) 49 | 50 | if (!nmsItem.isEmpty) { 51 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 52 | player.broadcastBreakEvent(nmsSlot) 53 | } 54 | } 55 | } 56 | } 57 | 58 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 59 | return when (slot) { 60 | EquipmentSlot.HAND -> getSelected() 61 | EquipmentSlot.OFF_HAND -> offhand[0] 62 | EquipmentSlot.FEET -> armorContents[0] 63 | EquipmentSlot.LEGS -> armorContents[1] 64 | EquipmentSlot.CHEST -> armorContents[2] 65 | EquipmentSlot.HEAD -> armorContents[3] 66 | } 67 | } -------------------------------------------------------------------------------- /tap-dongle/v1.19/src/main/kotlin/io/github/monun/tap/v1_19/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_19.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20.1/src/main/kotlin/io/github/monun/tap/v1_20_1/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20_1.fake 19 | 20 | import net.minecraft.core.registries.BuiltInRegistries 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_20_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | BuiltInRegistries.ENTITY_TYPE.forEach { type -> 38 | type.create(level)?.let { entity -> 39 | val bukkitClass = entity.bukkitEntity.javaClass 40 | val interfaces = bukkitClass.interfaces 41 | 42 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 43 | 44 | for (i in interfaces) { 45 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 46 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | @JvmStatic 54 | fun findType(bukkitClass: Class): EntityType<*> { 55 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 56 | } 57 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20.1/src/main/kotlin/io/github/monun/tap/v1_20_1/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20_1.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.entity.player.Inventory 23 | import net.minecraft.world.item.ItemStack 24 | import org.bukkit.craftbukkit.v1_20_R1.CraftEquipmentSlot 25 | import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer 26 | import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryPlayer 27 | import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack 28 | import org.bukkit.inventory.EquipmentSlot 29 | import org.bukkit.inventory.ItemStack as BukkitItemStack 30 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 31 | 32 | class NMSItemSupport : ItemSupport { 33 | override fun saveToJsonString(item: BukkitItemStack): String { 34 | val nmsItem = CraftItemStack.asNMSCopy(item) 35 | return nmsItem.save(CompoundTag()).toString() 36 | } 37 | 38 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 39 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 40 | 41 | nmsInventory.hurtArmor( 42 | nmsInventory.player.damageSources().lava(), 43 | attackDamage.toFloat(), 44 | Inventory.ALL_ARMOR_SLOTS 45 | ) 46 | } 47 | 48 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 49 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 50 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 51 | val nmsItem = nmsInventory.getItem(slot) 52 | 53 | if (!nmsItem.isEmpty) { 54 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 55 | player.broadcastBreakEvent(nmsSlot) 56 | } 57 | } 58 | } 59 | } 60 | 61 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 62 | return when (slot) { 63 | EquipmentSlot.HAND -> getSelected() 64 | EquipmentSlot.OFF_HAND -> offhand[0] 65 | EquipmentSlot.FEET -> armorContents[0] 66 | EquipmentSlot.LEGS -> armorContents[1] 67 | EquipmentSlot.CHEST -> armorContents[2] 68 | EquipmentSlot.HEAD -> armorContents[3] 69 | } 70 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20.1/src/main/kotlin/io/github/monun/tap/v1_20_1/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20_1.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20/src/main/kotlin/io/github/monun/tap/v1_20/fake/NMSEntityTypes.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20.fake 19 | 20 | import net.minecraft.core.registries.BuiltInRegistries 21 | import net.minecraft.server.MinecraftServer 22 | import net.minecraft.world.entity.EntityType 23 | import org.bukkit.Bukkit 24 | import org.bukkit.craftbukkit.v1_20_R1.CraftServer 25 | import org.bukkit.entity.Entity as BukkitEntity 26 | 27 | /** 28 | * @author Nemo 29 | */ 30 | internal object NMSEntityTypes { 31 | private val ENTITIES = HashMap, EntityType<*>>() 32 | 33 | init { 34 | val server: MinecraftServer = (Bukkit.getServer() as CraftServer).server 35 | val level = server.allLevels.first() 36 | 37 | BuiltInRegistries.ENTITY_TYPE.forEach { type -> 38 | type.create(level)?.let { entity -> 39 | val bukkitClass = entity.bukkitEntity.javaClass 40 | val interfaces = bukkitClass.interfaces 41 | 42 | ENTITIES[bukkitClass.asSubclass(BukkitEntity::class.java)] = type 43 | 44 | for (i in interfaces) { 45 | if (BukkitEntity::class.java.isAssignableFrom(i)) { 46 | ENTITIES[i.asSubclass(BukkitEntity::class.java)] = type 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | @JvmStatic 54 | fun findType(bukkitClass: Class): EntityType<*> { 55 | return ENTITIES[bukkitClass] ?: error("Unknown entity type $bukkitClass") 56 | } 57 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20/src/main/kotlin/io/github/monun/tap/v1_20/item/NMSItemSupport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20.item 19 | 20 | import io.github.monun.tap.item.ItemSupport 21 | import net.minecraft.nbt.CompoundTag 22 | import net.minecraft.world.entity.player.Inventory 23 | import net.minecraft.world.item.ItemStack 24 | import org.bukkit.craftbukkit.v1_20_R1.CraftEquipmentSlot 25 | import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer 26 | import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryPlayer 27 | import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack 28 | import org.bukkit.inventory.EquipmentSlot 29 | import org.bukkit.inventory.ItemStack as BukkitItemStack 30 | import org.bukkit.inventory.PlayerInventory as BukkitPlayerInventory 31 | 32 | class NMSItemSupport : ItemSupport { 33 | override fun saveToJsonString(item: BukkitItemStack): String { 34 | val nmsItem = CraftItemStack.asNMSCopy(item) 35 | return nmsItem.save(CompoundTag()).toString() 36 | } 37 | 38 | override fun damageArmor(playerInventory: BukkitPlayerInventory, attackDamage: Double) { 39 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 40 | 41 | nmsInventory.hurtArmor( 42 | nmsInventory.player.damageSources().lava(), 43 | attackDamage.toFloat(), 44 | Inventory.ALL_ARMOR_SLOTS 45 | ) 46 | } 47 | 48 | override fun damageSlot(playerInventory: BukkitPlayerInventory, slot: EquipmentSlot, damage: Int) { 49 | val nmsInventory = (playerInventory as CraftInventoryPlayer).inventory 50 | val nmsSlot = CraftEquipmentSlot.getNMS(slot) 51 | val nmsItem = nmsInventory.getItem(slot) 52 | 53 | if (!nmsItem.isEmpty) { 54 | nmsItem.hurtAndBreak(damage, (playerInventory.holder as CraftPlayer).handle) { player -> 55 | player.broadcastBreakEvent(nmsSlot) 56 | } 57 | } 58 | } 59 | } 60 | 61 | internal fun Inventory.getItem(slot: EquipmentSlot): ItemStack { 62 | return when (slot) { 63 | EquipmentSlot.HAND -> getSelected() 64 | EquipmentSlot.OFF_HAND -> offhand[0] 65 | EquipmentSlot.FEET -> armorContents[0] 66 | EquipmentSlot.LEGS -> armorContents[1] 67 | EquipmentSlot.CHEST -> armorContents[2] 68 | EquipmentSlot.HEAD -> armorContents[3] 69 | } 70 | } -------------------------------------------------------------------------------- /tap-dongle/v1.20/src/main/kotlin/io/github/monun/tap/v1_20/protocol/NMSPacketContainer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.v1_20.protocol 19 | 20 | import io.github.monun.tap.protocol.PacketContainer 21 | import net.minecraft.network.protocol.Packet 22 | import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer 23 | import org.bukkit.entity.Player 24 | 25 | 26 | class NMSPacketContainer(private val packet: Packet<*>) : PacketContainer { 27 | override fun sendTo(player: Player) { 28 | (player as CraftPlayer).handle.connection.send(packet, null) 29 | } 30 | } -------------------------------------------------------------------------------- /tap-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.configurationcache.extensions.capitalized 2 | 3 | dependencies { 4 | implementation(projectApi) 5 | } 6 | 7 | extra.apply { 8 | set("pluginName", rootProject.name.split('-').joinToString("") { it.capitalize() }) 9 | set("packageName", rootProject.name.replace("-", "")) 10 | set("kotlinVersion", Dependency.Kotlin.Version) 11 | set("paperVersion", Dependency.Paper.Version) 12 | } 13 | 14 | tasks { 15 | processResources { 16 | filesMatching("*.yml") { 17 | expand(project.properties) 18 | expand(extra.properties) 19 | } 20 | } 21 | 22 | fun registerJar( 23 | classifier: String, 24 | bundleProject: Project? = null, 25 | bundleTask: TaskProvider? = null 26 | ) = register("${classifier}Jar") { 27 | archiveBaseName.set(rootProject.name) 28 | archiveClassifier.set(classifier) 29 | 30 | from(sourceSets["main"].output) 31 | 32 | if (bundleProject != null) from(bundleProject.sourceSets["main"].output) 33 | 34 | if (bundleTask != null) { 35 | bundleTask.let { bundleJar -> 36 | dependsOn(bundleJar) 37 | from(zipTree(bundleJar.get().archiveFile)) 38 | } 39 | exclude("clip.yml") 40 | rename("bundle.yml", "plugin.yml") 41 | } else { 42 | exclude("bundle.yml") 43 | rename("clip.yml", "plugin.yml") 44 | } 45 | }.also { jar -> 46 | register("test${classifier.capitalized()}Jar") { 47 | val prefix = rootProject.name 48 | val plugins = rootProject.file(".server/plugins-$classifier") 49 | val update = File(plugins, "update") 50 | val regex = Regex("($prefix)(.*)(\\.jar)") 51 | 52 | from(jar) 53 | 54 | if (plugins.list()?.any { regex.matches(it) } == true) { 55 | into(update) 56 | } else { 57 | into(plugins) 58 | } 59 | 60 | doLast { 61 | update.mkdirs() 62 | File(update, "RELOAD").delete() 63 | } 64 | } 65 | } 66 | 67 | registerJar("dev", projectApi, coreDevJar) 68 | registerJar("reobf", projectApi, coreReobfJar) 69 | registerJar("clip") 70 | } 71 | 72 | -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/TapPlugin.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 Monun 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package io.github.monun.tap.plugin 19 | 20 | import io.github.monun.tap.plugin.test.TapTest 21 | import org.bukkit.command.Command 22 | import org.bukkit.command.CommandSender 23 | import org.bukkit.plugin.java.JavaPlugin 24 | 25 | class TapPlugin : JavaPlugin() { 26 | 27 | override fun onEnable() { 28 | TapTest.init(this) 29 | } 30 | 31 | override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { 32 | if (args.isEmpty()) 33 | return false 34 | 35 | if (args[0] == "simple") { 36 | TapTest.testSimpleAll() 37 | } else if (args[0] == "run") { 38 | TapTest.runTestComplexTestAll() 39 | } else if (args[0] == "stop") { 40 | TapTest.cancelTestComplexTestAll() 41 | } 42 | 43 | return true 44 | } 45 | } -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/TapTest.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test 2 | 3 | import io.github.monun.tap.plugin.test.unit.complex.TestFakeEntityPose 4 | import io.github.monun.tap.plugin.test.unit.simple.TestConfigSupport 5 | import io.github.monun.tap.plugin.test.unit.simple.TestPersistentDataSupport 6 | import io.github.monun.tap.plugin.test.unit.simple.TestNewVersionFetchSupport 7 | import org.bukkit.Bukkit 8 | import org.bukkit.event.HandlerList 9 | import org.bukkit.plugin.Plugin 10 | 11 | object TapTest { 12 | private lateinit var plugin: Plugin 13 | 14 | private val simpleTestMap: Map SimpleTestUnit> = mapOf( 15 | "persistent-data" to ::TestPersistentDataSupport, 16 | "config-test" to ::TestConfigSupport, 17 | "version-fetch-test" to ::TestNewVersionFetchSupport 18 | ) 19 | 20 | private val complexTestMap: Map ComplexTestUnit> = mapOf( 21 | "fake-entity-pose" to ::TestFakeEntityPose 22 | ) 23 | private val runningComplexTestList = mutableListOf() 24 | 25 | fun init(plugin: Plugin) { 26 | this.plugin = plugin 27 | } 28 | 29 | fun testSimpleAll() { 30 | simpleTestMap.forEach { (name, factory) -> 31 | val test = factory() 32 | test.name = name 33 | test.logger = plugin.logger 34 | 35 | test.message(buildString { 36 | repeat(10) { append('=') } 37 | append(" $name ") 38 | repeat(10) { append('=') } 39 | }) 40 | test.runCatching { test() }.onFailure { e -> 41 | e.printStackTrace() 42 | test.error("$name // TEST FAILED!") 43 | } 44 | } 45 | } 46 | 47 | fun runTestComplexTestAll() { 48 | runningComplexTestList += complexTestMap.map { (name, factory) -> 49 | val test = factory() 50 | test.name = name 51 | test.logger = plugin.logger 52 | test.register(plugin) 53 | test.task = Bukkit.getScheduler().runTaskTimer(plugin, test, 1L, 1L) 54 | Bukkit.getPluginManager().registerEvents(test, plugin) 55 | test 56 | } 57 | } 58 | 59 | fun cancelTestComplexTestAll() { 60 | runningComplexTestList.onEach { 61 | HandlerList.unregisterAll(it) 62 | it.task?.cancel() 63 | it.unregister() 64 | }.clear() 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/TestUnit.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test 2 | 3 | import net.kyori.adventure.text.Component 4 | import net.kyori.adventure.text.format.NamedTextColor 5 | import org.bukkit.Bukkit 6 | import org.bukkit.event.Listener 7 | import org.bukkit.plugin.Plugin 8 | import java.util.logging.Logger 9 | 10 | abstract class TestUnit { 11 | lateinit var name: String 12 | lateinit var logger: Logger 13 | 14 | fun message(message: String) { 15 | Bukkit.broadcast(Component.text(message).color(NamedTextColor.GRAY)) 16 | } 17 | 18 | fun error(message: String) { 19 | Bukkit.broadcast(Component.text(message).color(NamedTextColor.RED)) 20 | } 21 | } 22 | 23 | abstract class SimpleTestUnit : TestUnit() { 24 | abstract fun test() 25 | } 26 | 27 | abstract class ComplexTestUnit : TestUnit(), Listener, Runnable { 28 | var task: org.bukkit.scheduler.BukkitTask? = null 29 | 30 | abstract fun register(plugin: Plugin) 31 | 32 | abstract fun unregister() 33 | } -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/unit/complex/TestFakeEntityPose.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test.unit.complex 2 | 3 | import io.github.monun.tap.fake.FakeEntity 4 | import io.github.monun.tap.fake.FakeEntityServer 5 | import io.github.monun.tap.fake.tap 6 | import io.github.monun.tap.plugin.test.ComplexTestUnit 7 | import io.github.monun.tap.protocol.AnimationType 8 | import org.bukkit.Bukkit 9 | import org.bukkit.EntityEffect 10 | import org.bukkit.entity.Player 11 | import org.bukkit.entity.Pose 12 | import org.bukkit.event.EventHandler 13 | import org.bukkit.event.player.PlayerJoinEvent 14 | import org.bukkit.plugin.Plugin 15 | import org.bukkit.plugin.java.JavaPlugin 16 | import java.util.* 17 | import kotlin.random.Random.Default.nextInt 18 | 19 | class TestFakeEntityPose : ComplexTestUnit() { 20 | 21 | private lateinit var fakeEntityServer: FakeEntityServer 22 | private val map = mutableMapOf>() 23 | 24 | override fun register(plugin: Plugin) { 25 | fakeEntityServer = FakeEntityServer.create(plugin as JavaPlugin) 26 | Bukkit.getOnlinePlayers().forEach { 27 | fakeEntityServer.addPlayer(it) 28 | spawnBody(it) 29 | } 30 | } 31 | 32 | override fun unregister() { 33 | fakeEntityServer.clear() 34 | } 35 | 36 | override fun run() { 37 | if (nextInt(100) == 0) { 38 | map.values.forEach { entity -> 39 | // entity.playEffect(EntityEffect.HURT) 40 | // entity.playAnimation(AnimationType.TAKE_DAMAGE) 41 | entity.playHurtAnimation() 42 | } 43 | } 44 | 45 | fakeEntityServer.update() 46 | } 47 | 48 | @EventHandler 49 | fun onPlayerJoin(event: PlayerJoinEvent) { 50 | event.player.let { 51 | spawnBody(it) 52 | fakeEntityServer.addPlayer(it) 53 | } 54 | 55 | } 56 | 57 | @EventHandler 58 | fun onPlayerQuit(event: PlayerJoinEvent) { 59 | event.player.let { 60 | despawnBody(it) 61 | fakeEntityServer.removePlayer(it) 62 | } 63 | } 64 | 65 | private fun spawnBody(player: Player) { 66 | fakeEntityServer.spawnPlayer(player.location, "●▅▇█▇▆▅▄▇", player.playerProfile.properties).apply { 67 | updateMetadata { 68 | tap().pose = Pose.SLEEPING 69 | } 70 | }.also { 71 | map[player.uniqueId] = it 72 | } 73 | } 74 | 75 | private fun despawnBody(player: Player) { 76 | map.remove(player.uniqueId)?.remove() 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/unit/simple/TestConfigSupport.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test.unit.simple 2 | 3 | import io.github.monun.tap.config.Config 4 | import io.github.monun.tap.config.ConfigSupport 5 | import io.github.monun.tap.config.compute 6 | import io.github.monun.tap.plugin.test.SimpleTestUnit 7 | import org.bukkit.configuration.file.YamlConfiguration 8 | 9 | class TestConfigSupport : SimpleTestUnit() { 10 | override fun test() { 11 | val separated = YamlConfiguration() 12 | val nonSeparated = YamlConfiguration() 13 | val config = TestParrotConfig() 14 | 15 | ConfigSupport.compute(config, separated, true) 16 | ConfigSupport.compute(config, nonSeparated, false) 17 | 18 | message("클래스 분리\n${separated.saveToString()}") 19 | message("클래스 미분리\n${nonSeparated.saveToString()}") 20 | 21 | message("데이터 변경") 22 | message("name: 구구") 23 | message("age: 30") 24 | message("color: blue") 25 | 26 | nonSeparated["name"] = "구구" 27 | nonSeparated["age"] = 30 28 | nonSeparated["color"] = "blue" 29 | 30 | ConfigSupport.compute(config, nonSeparated, false) 31 | message("${config.name} ${config.age} ${config.color}") 32 | } 33 | } 34 | 35 | open class TestBirdConfig { 36 | @Config 37 | var name: String = "bird" 38 | 39 | @Config 40 | var age: Int = 15 41 | } 42 | 43 | class TestParrotConfig : TestBirdConfig() { 44 | @Config 45 | var color: String = "red" 46 | } -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/unit/simple/TestNewVersionFetchSupport.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test.unit.simple 2 | 3 | import io.github.monun.tap.plugin.test.SimpleTestUnit 4 | import org.bukkit.Bukkit 5 | 6 | class TestNewVersionFetchSupport : SimpleTestUnit() { 7 | override fun test() { 8 | val oldMinecraftVersionMethod = with("(?<=\\(MC: )[\\d.]+?(?=\\))".toPattern().matcher(Bukkit.getVersion())) { 9 | when { 10 | find() -> group() 11 | else -> throw NoSuchElementException("No such minecraft version exists") 12 | } 13 | } 14 | 15 | val oldBukkitVersionMethod = with("v\\d+_\\d+_R\\d+".toPattern().matcher(Bukkit.getServer()::class.java.`package`.name)) { 16 | when { 17 | find() -> group() 18 | else -> throw NoSuchElementException("No such bukkit version exists") 19 | } 20 | } 21 | 22 | 23 | message("fetched minecraft version (old): $oldMinecraftVersionMethod") 24 | message("fetched minecraft version (new): ${Bukkit.getServer().minecraftVersion}") 25 | 26 | message("fetched bukkit version (old): $oldBukkitVersionMethod") 27 | message("fetched bukkit version (new): ${Bukkit.getServer().bukkitVersion}") 28 | } 29 | } -------------------------------------------------------------------------------- /tap-plugin/src/main/kotlin/io/github/monun/tap/plugin/test/unit/simple/TestPersistentDataSupport.kt: -------------------------------------------------------------------------------- 1 | package io.github.monun.tap.plugin.test.unit.simple 2 | 3 | import io.github.monun.tap.data.PersistentDataKeychain 4 | import io.github.monun.tap.data.getValue 5 | import io.github.monun.tap.data.persistentData 6 | import io.github.monun.tap.plugin.test.SimpleTestUnit 7 | import kotlinx.serialization.Serializable 8 | import net.kyori.adventure.text.Component.text 9 | import org.bukkit.Location 10 | import org.bukkit.Material 11 | import org.bukkit.inventory.ItemStack 12 | import org.bukkit.util.Vector 13 | import java.time.Instant 14 | import java.util.* 15 | 16 | class TestPersistentDataSupport : SimpleTestUnit() { 17 | 18 | companion object { 19 | private val item = ItemStack(Material.STONE) 20 | } 21 | 22 | // level = 테스트 마다 +1 23 | // power = 테스트 마다 +0.15 24 | // timestamp = 테스트 마다 현재 시간 25 | // complex = 테스트 마다 numbers에 count 추가, float에 1.1 곱함 26 | // message = 테스트 마다 문자 하나씩 추가 27 | override fun test() { 28 | item.apply { 29 | val prevData = itemMeta!!.persistentData 30 | val prevLevel = prevData[TestKeychain.level] ?: 0 31 | val prevPower = prevData[TestKeychain.power] ?: 0.0 32 | val prevComplex = prevData[TestKeychain.complex] ?: TestComplexData(emptyList(), 1.0f) 33 | val prevMessage = prevData["message"] ?: "" 34 | 35 | //add data 36 | editMeta { meta -> 37 | meta.persistentData.let { data -> 38 | 39 | data[TestKeychain.level] = prevLevel + 1 40 | data[TestKeychain.power] = prevPower + 0.15 41 | data[TestKeychain.timestamp] = Instant.now().toString() 42 | data[TestKeychain.complex] = 43 | TestComplexData( 44 | prevComplex.numbers + listOf(prevComplex.numbers.count()), 45 | prevComplex.float * 1.1f 46 | ) 47 | data[TestKeychain.loc] = Location(null, 1.0, 2.0, 3.0, 4.0F, 5.0F) 48 | data[TestKeychain.vector] = Vector(1.0, 2.0, 3.0) 49 | data[TestKeychain.uuid] = UUID.randomUUID() 50 | data[TestKeychain.enum] = TestEnum.values().random() 51 | data[TestKeychain.itemStack] = 52 | ItemStack(Material.STONE).apply { editMeta { it.displayName(text("Hello world")) } } 53 | data[TestKeychain.boolean] = true 54 | data["message"] = prevMessage + (prevMessage.lastOrNull()?.inc() ?: "A") 55 | } 56 | } 57 | 58 | itemMeta!!.persistentData.let { data -> 59 | message("level: ${data[TestKeychain.level]}") 60 | message("power: ${data[TestKeychain.power]}") 61 | message("timestamp: ${data[TestKeychain.timestamp]}") 62 | message("complex: ${data[TestKeychain.complex]}") 63 | message("loc: ${data[TestKeychain.loc]}") 64 | message("vector: ${data[TestKeychain.vector]}") 65 | message("uuid: ${data[TestKeychain.uuid]}") 66 | message("enum: ${data[TestKeychain.enum]}") 67 | message("data: ${data[TestKeychain.itemStack]}") 68 | message("bool: ${data[TestKeychain.boolean]}") 69 | val message: String? by data 70 | message("message: $message") 71 | 72 | require(data[TestKeychain.level] == prevLevel + 1) { "level" } 73 | require(data[TestKeychain.power] == prevPower + 0.15) { "power" } 74 | } 75 | } 76 | } 77 | } 78 | 79 | object TestKeychain : PersistentDataKeychain() { 80 | val level = primitive("level") 81 | val power = primitive("power") 82 | val timestamp = primitive("timestamp") 83 | val loc = location("loc") 84 | val vector = vector("vector") 85 | val uuid = uuid("uuid") 86 | val complex = complex("complex") 87 | val enum = enum("enum") 88 | val itemStack = itemStack("itemStack") 89 | val boolean = boolean("bool") 90 | } 91 | 92 | @Serializable 93 | data class TestComplexData( 94 | val numbers: List, 95 | val float: Float 96 | ) 97 | 98 | enum class TestEnum { 99 | A, B, C 100 | } -------------------------------------------------------------------------------- /tap-plugin/src/main/resources/bundle.yml: -------------------------------------------------------------------------------- 1 | name: ${pluginName} 2 | version: ${version} 3 | main: ${group}.${packageName}.plugin.${pluginName}Plugin 4 | api-version: ${paperVersion} 5 | commands: 6 | test: 7 | description: Test command 8 | usage: /${pluginName} test 9 | tab-complete: 0 10 | libraries: 11 | - org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion} 12 | - org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion} 13 | - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4 14 | - org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1 15 | - org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.1 16 | - org.mariuszgromada.math:MathParser.org-mXparser:5.0.6 -------------------------------------------------------------------------------- /tap-plugin/src/main/resources/clip.yml: -------------------------------------------------------------------------------- 1 | name: ${pluginName} 2 | version: ${version} 3 | main: ${group}.${packageName}.plugin.${pluginName}Plugin 4 | api-version: ${paperVersion} 5 | commands: 6 | test: 7 | description: Test command 8 | usage: /${pluginName} test 9 | tab-complete: 0 10 | libraries: 11 | - org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion} 12 | - org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion} 13 | - ${group}:${packageName}-core:${version} -------------------------------------------------------------------------------- /tap-publish/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `maven-publish` 3 | signing 4 | } 5 | 6 | projectPlugin.tasks.named("clipJar") { 7 | dependsOn(tasks.named("publishApiPublicationToServerRepository")) 8 | dependsOn(tasks.named("publishCorePublicationToServerRepository")) 9 | } 10 | 11 | publishing { 12 | repositories { 13 | mavenLocal() 14 | 15 | maven { 16 | name = "server" 17 | url = rootProject.uri(".server/libraries") 18 | } 19 | 20 | maven { 21 | name = "central" 22 | 23 | credentials.runCatching { 24 | val nexusUsername: String by project 25 | val nexusPassword: String by project 26 | username = nexusUsername 27 | password = nexusPassword 28 | }.onFailure { 29 | logger.warn("Failed to load nexus credentials, Check the gradle.properties") 30 | } 31 | 32 | url = uri( 33 | if ("SNAPSHOT" in version as String) { 34 | "https://s01.oss.sonatype.org/content/repositories/snapshots/" 35 | } else { 36 | "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" 37 | } 38 | ) 39 | } 40 | } 41 | 42 | publications { 43 | fun MavenPublication.setup(target: Project) { 44 | artifactId = target.name 45 | from(target.components["java"]) 46 | artifact(target.tasks["sourcesJar"]) 47 | artifact(target.tasks["dokkaJar"]) 48 | 49 | pom { 50 | name.set(target.name) 51 | description.set("PaperMC extension library written in Kotlin") 52 | url.set("https://github.com/monun/${rootProject.name}") 53 | 54 | licenses { 55 | license { 56 | name.set("GNU General Public License version 3") 57 | url.set("https://opensource.org/licenses/GPL-3.0") 58 | } 59 | } 60 | 61 | developers { 62 | developer { 63 | id.set("monun") 64 | name.set("Monun") 65 | email.set("monun1010@gmail.com") 66 | url.set("https://github.com/monun") 67 | roles.addAll("developer") 68 | timezone.set("Asia/Seoul") 69 | } 70 | } 71 | 72 | scm { 73 | connection.set("scm:git:git://github.com/monun/${rootProject.name}.git") 74 | developerConnection.set("scm:git:ssh://github.com:monun/${rootProject.name}.git") 75 | url.set("https://github.com/monun/${rootProject.name}") 76 | } 77 | } 78 | } 79 | 80 | create("api") { 81 | setup(projectApi) 82 | } 83 | 84 | create("core") { 85 | setup(projectCore) 86 | artifact(coreReobfJar) 87 | } 88 | 89 | } 90 | } 91 | 92 | signing { 93 | isRequired = true 94 | sign(publishing.publications["api"], publishing.publications["core"]) 95 | } 96 | --------------------------------------------------------------------------------