From 93ae66890c78c2cfae8900d07e2f8ba6eb7b3e0a Mon Sep 17 00:00:00 2001 From: Shynixn Date: Fri, 24 Jan 2025 14:58:54 +0100 Subject: [PATCH 1/5] #74 Removed obsolete placeholder implementation. --- .gitignore | 3 + build.gradle.kts | 143 +++++++------- docs/wiki/docs/README.md | 1 - gradle.properties | 1 + gradle/wrapper/gradle-wrapper.properties | 4 +- settings.gradle.kts | 6 - .../MCTennisDependencyInjectionModule.kt | 137 ++++++++----- .../shynixn/mctennis/MCTennisLanguageImpl.kt | 120 ++++++------ .../github/shynixn/mctennis/MCTennisPlugin.kt | 44 ++--- .../mctennis/contract/BedrockService.kt | 16 -- .../{Language.kt => MCTennisLanguage.kt} | 2 +- .../mctennis/contract/PlaceHolderService.kt | 10 - .../mctennis/entity/TennisBallSettings.kt | 11 -- .../mctennis/enumeration/PlaceHolder.kt | 182 +++++++++++++++--- .../mctennis/enumeration/PluginDependency.kt | 20 -- .../mctennis/enumeration/VisibilityType.kt | 8 - .../shynixn/mctennis/impl/TennisGameImpl.kt | 47 +++-- .../MCTennisCommandExecutor.kt | 42 ++-- .../mctennis/impl/listener/GameListener.kt | 3 +- .../mctennis/impl/listener/PacketListener.kt | 3 +- .../mctennis/impl/listener/TennisListener.kt | 7 +- .../impl/physic/ArmorstandEntityComponent.kt | 16 -- .../impl/physic/SlimeEntityComponent.kt | 21 +- .../impl/service/BedrockServiceImpl.kt | 95 --------- .../DependencyGeyserSpigotServiceImpl.kt | 12 -- .../DependencyPlaceholderApiServiceImpl.kt | 99 ---------- .../mctennis/impl/service/GameServiceImpl.kt | 9 +- .../impl/service/PlaceHolderServiceImpl.kt | 181 ----------------- .../impl/service/TennisBallFactoryImpl.kt | 104 ++-------- src/main/resources/arena_sample.yml | 5 - storage/court.yml | 2 - 31 files changed, 492 insertions(+), 862 deletions(-) create mode 100644 .gitignore delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/contract/BedrockService.kt rename src/main/kotlin/com/github/shynixn/mctennis/contract/{Language.kt => MCTennisLanguage.kt} (97%) delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/contract/PlaceHolderService.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/enumeration/PluginDependency.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/enumeration/VisibilityType.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/impl/service/BedrockServiceImpl.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyGeyserSpigotServiceImpl.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyPlaceholderApiServiceImpl.kt delete mode 100644 src/main/kotlin/com/github/shynixn/mctennis/impl/service/PlaceHolderServiceImpl.kt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0d53d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.gradle +.idea +build diff --git a/build.gradle.kts b/build.gradle.kts index 5518035..715a6d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,62 +11,27 @@ group = "com.github.shynixn" version = "1.13.0" repositories { + mavenLocal() mavenCentral() maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - maven("https://repo.extendedclip.com/content/repositories/placeholderapi") - maven("https://repo.opencollab.dev/main/") - maven(System.getenv("SHYNIXN_MCUTILS_REPOSITORY")) // All MCUTILS libraries are private and not OpenSource. -} - -tasks.register("printVersion") { - println(version) + maven(System.getenv("SHYNIXN_MCUTILS_REPOSITORY_2025")) // All MCUTILS libraries are private and not OpenSource. } dependencies { // Compile Only compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT") - compileOnly("me.clip:placeholderapi:2.11.6") - compileOnly("org.geysermc.geyser:api:2.2.0-SNAPSHOT") // Plugin.yml Shade dependencies implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:2.20.0") implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:2.20.0") - implementation("com.google.inject:guice:5.0.1") implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.3.0") implementation("com.fasterxml.jackson.core:jackson-databind:2.2.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") - implementation("com.google.code.gson:gson:2.8.6") // Custom dependencies - implementation("com.github.shynixn.mcutils:common:2024.39") - implementation("com.github.shynixn.mcutils:packet:2024.51") - implementation("com.github.shynixn.mcutils:sign:2024.3") - implementation("com.github.shynixn.mcutils:guice:2024.2") - - // Test - testImplementation(kotlin("test")) - testImplementation("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT") - testImplementation("org.mockito:mockito-core:2.23.0") -} - -tasks.test { - useJUnitPlatform() - testLogging.showStandardStreams = true - failFast = true - - testLogging { - events( - org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED, - org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED, - org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED, - org.gradle.api.tasks.testing.logging.TestLogEvent.STARTED - ) - displayGranularity = 0 - showExceptions = true - showCauses = true - showStackTraces = true - exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - } + implementation("com.github.shynixn.mcutils:common:2025.1") + implementation("com.github.shynixn.mcutils:packet:2025.1") + implementation("com.github.shynixn.mcutils:sign:2025.1") } tasks.withType { @@ -83,7 +48,7 @@ java { */ tasks.withType { dependsOn("jar") - archiveName = "${baseName}-${version}-shadowjar.${extension}" + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-shadowjar.${archiveExtension.get()}") exclude("DebugProbesKt.bin") exclude("module-info.class") } @@ -102,8 +67,8 @@ tasks.register("pluginJars") { */ tasks.register("relocatePluginJar", com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class.java) { dependsOn("shadowJar") - from(zipTree(File("./build/libs/" + (tasks.getByName("shadowJar") as Jar).archiveName))) - archiveName = "${baseName}-${version}-relocate.${extension}" + from(zipTree(File("./build/libs/" + (tasks.getByName("shadowJar") as Jar).archiveFileName.get()))) + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-relocate.${archiveExtension.get()}") relocate("com.fasterxml", "com.github.shynixn.mctennis.lib.com.fasterxml") relocate("com.github.shynixn.mcutils", "com.github.shynixn.mctennis.lib.com.github.shynixn.mcutils") } @@ -113,9 +78,9 @@ tasks.register("relocatePluginJar", com.github.jengelman.gradle.plugins.shadow.t */ tasks.register("pluginJarLatest", com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class.java) { dependsOn("relocatePluginJar") - from(zipTree(File("./build/libs/" + (tasks.getByName("relocatePluginJar") as Jar).archiveName))) - archiveName = "${baseName}-${version}-latest.${extension}" - // destinationDir = File("C:\\temp\\plugins") + from(zipTree(File("./build/libs/" + (tasks.getByName("relocatePluginJar") as Jar).archiveFileName.get()))) + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-latest.${archiveExtension.get()}") + // destinationDirectory.set(File("C:\\temp\\plugins")) exclude("com/github/shynixn/mctennis/lib/com/github/shynixn/mcutils/packet/nms/v1_8_R3/**") exclude("com/github/shynixn/mctennis/lib/com/github/shynixn/mcutils/packet/nms/v1_9_R2/**") @@ -147,9 +112,9 @@ tasks.register("pluginJarLatest", com.github.jengelman.gradle.plugins.shadow.tas */ tasks.register("pluginJarPremium", com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class.java) { dependsOn("relocatePluginJar") - from(zipTree(File("./build/libs/" + (tasks.getByName("relocatePluginJar") as Jar).archiveName))) - archiveName = "${baseName}-${version}-premium.${extension}" - // destinationDir = File("C:\\temp\\plugins") + from(zipTree(File("./build/libs/" + (tasks.getByName("relocatePluginJar") as Jar).archiveFileName.get()))) + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-premium.${archiveExtension.get()}") + // destinationDirectory.set(File("C:\\temp\\plugins")) exclude("com/github/shynixn/mcutils/**") exclude("com/github/shynixn/mccoroutine/**") @@ -167,12 +132,11 @@ tasks.register("pluginJarPremium", com.github.jengelman.gradle.plugins.shadow.ta */ tasks.register("relocateLegacyPluginJar", com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class.java) { dependsOn("shadowJar") - from(zipTree(File("./build/libs/" + (tasks.getByName("shadowJar") as Jar).archiveName))) - archiveName = "${baseName}-${version}-legacy-relocate.${extension}" + from(zipTree(File("./build/libs/" + (tasks.getByName("shadowJar") as Jar).archiveFileName.get()))) + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-legacy-relocate.${archiveExtension.get()}") relocate("com.github.shynixn.mcutils", "com.github.shynixn.mctennis.lib.com.github.shynixn.mcutils") relocate("kotlin", "com.github.shynixn.mctennis.lib.kotlin") relocate("org.intellij", "com.github.shynixn.mctennis.lib.org.intelli") - relocate("org.aopalliance", "com.github.shynixn.mctennis.lib.org.aopalliance") relocate("org.checkerframework", "com.github.shynixn.mctennis.lib.org.checkerframework") relocate("org.jetbrains", "com.github.shynixn.mctennis.lib.org.jetbrains") relocate("org.slf4j", "com.github.shynixn.mctennis.lib.org.slf4j") @@ -191,9 +155,10 @@ tasks.register("relocateLegacyPluginJar", com.github.jengelman.gradle.plugins.sh */ tasks.register("pluginJarLegacy", com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class.java) { dependsOn("relocateLegacyPluginJar") - from(zipTree(File("./build/libs/" + (tasks.getByName("relocateLegacyPluginJar") as Jar).archiveName))) - archiveName = "${baseName}-${version}-legacy.${extension}" + from(zipTree(File("./build/libs/" + (tasks.getByName("relocateLegacyPluginJar") as Jar).archiveFileName.get()))) + archiveFileName.set("${archiveBaseName.get()}-${archiveVersion.get()}-legacy.${archiveExtension.get()}") // destinationDir = File("C:\\temp\\plugins") + exclude("com/github/shynixn/mcutils/**") exclude("org/**") exclude("kotlin/**") @@ -207,29 +172,73 @@ tasks.register("pluginJarLegacy", com.github.jengelman.gradle.plugins.shadow.tas tasks.register("languageFile") { val kotlinSrcFolder = project.sourceSets.toList()[0].allJava.srcDirs.first { e -> e.endsWith("kotlin") } - val contractFile = kotlinSrcFolder.resolve("com/github/shynixn/mctennis/contract/Language.kt") + val contractFile = kotlinSrcFolder.resolve("com/github/shynixn/mctennis/contract/MCTennisLanguage.kt") val resourceFile = kotlinSrcFolder.parentFile.resolve("resources").resolve("lang").resolve("en_us.yml") val lines = resourceFile.readLines() - val contents = ArrayList() - contents.add("package com.github.shynixn.mctennis.contract") - contents.add("") - contents.add("import com.github.shynixn.mcutils.common.language.LanguageItem") - contents.add("import com.github.shynixn.mcutils.common.language.LanguageProvider") - contents.add("") - contents.add("interface Language : LanguageProvider {") + val contractContents = ArrayList() + contractContents.add("package com.github.shynixn.mctennis.contract") + contractContents.add("") + contractContents.add("import com.github.shynixn.mcutils.common.language.LanguageItem") + contractContents.add("import com.github.shynixn.mcutils.common.language.LanguageProvider") + contractContents.add("") + contractContents.add("interface MCTennisLanguage : LanguageProvider {") for (key in lines) { if (key.toCharArray()[0].isLetter()) { - contents.add(" var ${key} LanguageItem") - contents.add("") + contractContents.add(" var ${key} LanguageItem") + contractContents.add("") } } - contents.removeLast() - contents.add("}") + contractContents.removeLast() + contractContents.add("}") contractFile.printWriter().use { out -> - for (line in contents) { + for (line in contractContents) { out.println(line) } } + + val implFile = kotlinSrcFolder.resolve("com/github/shynixn/mctennis/MCTennisLanguageImpl.kt") + val implContents = ArrayList() + implContents.add("package com.github.shynixn.mctennis") + implContents.add("") + implContents.add("import com.github.shynixn.mcutils.common.language.LanguageItem") + implContents.add("import com.github.shynixn.mctennis.contract.MCTennisLanguage") + implContents.add("") + implContents.add("class MCTennisLanguageImpl : MCTennisLanguage {") + implContents.add(" override val names: List\n" + + " get() = listOf(\"en_us\", \"es_es\", \"zh_cn\")") + + for (i in 0 until lines.size) { + val key = lines[i] + + if (key.toCharArray()[0].isLetter()) { + var text : String + + var j = i + while (true){ + if(lines[j].contains("text:")){ + text = lines[j] + break + } + j++ + } + + implContents.add(" override var ${key.replace(":","")} = LanguageItem(${text.replace(" text: ","")})") + implContents.add("") + } + } + implContents.removeLast() + implContents.add("}") + + implFile.printWriter().use { out -> + for (line in implContents) { + out.println(line) + } + } +} + + +tasks.register("printVersion") { + println(version) } diff --git a/docs/wiki/docs/README.md b/docs/wiki/docs/README.md index 7114103..5b55d15 100644 --- a/docs/wiki/docs/README.md +++ b/docs/wiki/docs/README.md @@ -7,7 +7,6 @@ MCTennis is a spigot plugin to play tennis games in Minecraft. * Adds a new playable tennis minigame * A moving TennisBall without any resource pack * A customizable physic engine for the TennisBall -* Additionally, works on Bedrock Clients using Geyser * PlaceHolderApi Support * Multiple games per server (Patreon Only) diff --git a/gradle.properties b/gradle.properties index 7fc6f1f..47e8cf5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,2 @@ kotlin.code.style=official +org.gradle.jvmargs=-Xms4g diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fe753c9..81aa1c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists \ No newline at end of file +zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 4113f50..70aa72f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1 @@ rootProject.name = "mctennis" - -pluginManagement { - plugins { - kotlin("jvm") version "1.6.21" - } -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisDependencyInjectionModule.kt b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisDependencyInjectionModule.kt index 2b9093e..c087dbb 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisDependencyInjectionModule.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisDependencyInjectionModule.kt @@ -2,17 +2,26 @@ package com.github.shynixn.mctennis import com.fasterxml.jackson.core.type.TypeReference import com.github.shynixn.mccoroutine.bukkit.launch -import com.github.shynixn.mctennis.contract.* +import com.github.shynixn.mctennis.contract.GameService +import com.github.shynixn.mctennis.contract.MCTennisLanguage +import com.github.shynixn.mctennis.contract.TennisBallFactory import com.github.shynixn.mctennis.entity.TennisArena -import com.github.shynixn.mctennis.enumeration.PluginDependency -import com.github.shynixn.mctennis.impl.service.* +import com.github.shynixn.mctennis.impl.commandexecutor.MCTennisCommandExecutor +import com.github.shynixn.mctennis.impl.listener.GameListener +import com.github.shynixn.mctennis.impl.listener.PacketListener +import com.github.shynixn.mctennis.impl.listener.TennisListener +import com.github.shynixn.mctennis.impl.service.GameServiceImpl +import com.github.shynixn.mctennis.impl.service.TennisBallFactoryImpl import com.github.shynixn.mcutils.common.ConfigurationService import com.github.shynixn.mcutils.common.ConfigurationServiceImpl import com.github.shynixn.mcutils.common.CoroutineExecutor import com.github.shynixn.mcutils.common.chat.ChatMessageService import com.github.shynixn.mcutils.common.command.CommandService import com.github.shynixn.mcutils.common.command.CommandServiceImpl +import com.github.shynixn.mcutils.common.di.DependencyInjectionModule import com.github.shynixn.mcutils.common.item.ItemService +import com.github.shynixn.mcutils.common.language.globalChatMessageService +import com.github.shynixn.mcutils.common.language.globalPlaceHolderService import com.github.shynixn.mcutils.common.physic.PhysicObjectDispatcher import com.github.shynixn.mcutils.common.physic.PhysicObjectDispatcherImpl import com.github.shynixn.mcutils.common.physic.PhysicObjectService @@ -23,17 +32,17 @@ import com.github.shynixn.mcutils.common.repository.Repository import com.github.shynixn.mcutils.common.repository.YamlFileRepositoryImpl import com.github.shynixn.mcutils.common.sound.SoundService import com.github.shynixn.mcutils.common.sound.SoundServiceImpl -import com.github.shynixn.mcutils.guice.DependencyInjectionModule import com.github.shynixn.mcutils.packet.api.PacketService import com.github.shynixn.mcutils.packet.api.RayTracingService -import com.github.shynixn.mcutils.packet.impl.service.* +import com.github.shynixn.mcutils.packet.impl.service.ChatMessageServiceImpl +import com.github.shynixn.mcutils.packet.impl.service.ItemServiceImpl +import com.github.shynixn.mcutils.packet.impl.service.PacketServiceImpl +import com.github.shynixn.mcutils.packet.impl.service.RayTracingServiceImpl import com.github.shynixn.mcutils.sign.SignService import com.github.shynixn.mcutils.sign.SignServiceImpl -import org.bukkit.Bukkit import org.bukkit.plugin.Plugin -import java.util.logging.Level -class MCTennisDependencyInjectionModule(private val plugin: Plugin) : DependencyInjectionModule() { +class MCTennisDependencyInjectionModule(private val plugin: MCTennisPlugin, private val language: MCTennisLanguage) { companion object { val areLegacyVersionsIncluded: Boolean by lazy { try { @@ -45,20 +54,12 @@ class MCTennisDependencyInjectionModule(private val plugin: Plugin) : Dependency } } - /** - * Configures the business logic tree. - */ - override fun configure() { - // Common - addService(plugin) - addService { - val chatMessageService = getService() - val language = MCTennisLanguageImpl() - language.chatMessageService = chatMessageService - language.placeHolderFun = - { text, player -> getService().replacePlaceHolders(text, player) } - language - } + fun build(): DependencyInjectionModule { + val module = DependencyInjectionModule() + + // Params + module.addService(plugin) + module.addService(language) // Repositories val tennisArenaRepository = YamlFileRepositoryImpl(plugin, @@ -67,39 +68,83 @@ class MCTennisDependencyInjectionModule(private val plugin: Plugin) : Dependency listOf("arena_sample.yml"), object : TypeReference() {}) val cacheTennisArenaRepository = CachedRepositoryImpl(tennisArenaRepository) - addService>(cacheTennisArenaRepository) - addService>(cacheTennisArenaRepository) + module.addService>(cacheTennisArenaRepository) + module.addService>(cacheTennisArenaRepository) - // Services - addService { - SignServiceImpl(plugin, getService(), getService().noPermissionMessage.text) - } - addService { - PhysicObjectServiceImpl(plugin, getService()) + // Library Services + module.addService { + com.github.shynixn.mcutils.common.placeholder.PlaceHolderServiceImpl( + plugin + ) } - addService(CommandServiceImpl(object : CoroutineExecutor { + module.addService(CommandServiceImpl(object : CoroutineExecutor { override fun execute(f: suspend () -> Unit) { plugin.launch { f.invoke() } } })) - addService(ChatMessageServiceImpl(plugin)) - addService(PhysicObjectDispatcherImpl(plugin)) - addService(ConfigurationServiceImpl(plugin)) - addService(SoundServiceImpl(plugin)) - addService(PacketServiceImpl(plugin)) - addService(ItemServiceImpl()) - addService() - addService() - addService() - addService() + module.addService { + SignServiceImpl(plugin, module.getService(), language.noPermissionMessage.text) + } + module.addService { + PhysicObjectServiceImpl(plugin, module.getService()) + } + module.addService(ChatMessageServiceImpl(plugin)) + module.addService(PhysicObjectDispatcherImpl(plugin)) + module.addService(ConfigurationServiceImpl(plugin)) + module.addService(SoundServiceImpl(plugin)) + module.addService(PacketServiceImpl(plugin)) + module.addService(ItemServiceImpl()) + module.addService(RayTracingServiceImpl()) + + // Services + module.addService { + MCTennisCommandExecutor( + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService() + ) + } + module.addService { + GameListener(module.getService(), module.getService()) + } + module.addService { + PacketListener(module.getService(), module.getService(), module.getService()) + } + module.addService { + TennisListener(module.getService(), module.getService(), module.getService()) + } - if (Bukkit.getPluginManager().getPlugin(PluginDependency.PLACEHOLDERAPI.pluginName) != null) { - addService() - plugin.logger.log(Level.INFO, "Loaded dependency ${PluginDependency.PLACEHOLDERAPI.pluginName}.") - } else { - addService() + module.addService { + GameServiceImpl( + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService() + ) + } + module.addService { + TennisBallFactoryImpl( + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService(), + module.getService() + ) } + + plugin.globalChatMessageService = module.getService() + plugin.globalPlaceHolderService = module.getService() + return module } } diff --git a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt index 988405e..269718e 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt @@ -1,120 +1,116 @@ package com.github.shynixn.mctennis -import com.github.shynixn.mctennis.contract.Language import com.github.shynixn.mcutils.common.language.LanguageItem -import com.github.shynixn.mcutils.common.language.LanguageProviderImpl +import com.github.shynixn.mctennis.contract.MCTennisLanguage -class MCTennisLanguageImpl() : Language, LanguageProviderImpl() { - override val names: List - get() = listOf("en_us") +class MCTennisLanguageImpl : MCTennisLanguage { + override val names: List + get() = listOf("en_us", "es_es", "zh_cn") + override var gameStartingMessage = LanguageItem("[&9MCTennis&f] Game is starting in %1$1d seconds.") - override var gameStartingMessage: LanguageItem = LanguageItem() + override var gameStartCancelledMessage = LanguageItem("[&9MCTennis&f] Game start has been cancelled.") - override var gameStartCancelledMessage: LanguageItem = LanguageItem() + override var gameDoesNotExistMessage = LanguageItem("[&9MCTennis&f] Game %1$1s does not exist.") - override var gameDoesNotExistMessage: LanguageItem = LanguageItem() + override var noPermissionForGameMessage = LanguageItem("[&9MCTennis&f] You do not have permission to join game %1$1s.") - override var noPermissionForGameMessage: LanguageItem = LanguageItem() + override var noPermissionMessage = LanguageItem("[&9MCTennis&f] You do not have permission.") - override var noPermissionMessage: LanguageItem = LanguageItem() + override var locationTypeDoesNotExistMessage = LanguageItem("[&9MCTennis&f] This location type is not known. For more locations, open the arena.yml.") - override var locationTypeDoesNotExistMessage: LanguageItem = LanguageItem() + override var spawnPointSetMessage = LanguageItem("[&9MCTennis&f] Location was set on %1$1s.") - override var spawnPointSetMessage: LanguageItem = LanguageItem() + override var gameAlreadyExistsMessage = LanguageItem("[&9MCTennis&f] Game %1$1s already exists.") - override var gameAlreadyExistsMessage: LanguageItem = LanguageItem() + override var enabledArenaMessage = LanguageItem("[&9MCTennis&f] Game enable state was set to %1$1s.") - override var enabledArenaMessage: LanguageItem = LanguageItem() + override var gameIsFullMessage = LanguageItem("[&9MCTennis&f] Game is already full.") - override var gameIsFullMessage: LanguageItem = LanguageItem() + override var gameCreatedMessage = LanguageItem("[&9MCTennis&f] Created game %1$1s.") - override var gameCreatedMessage: LanguageItem = LanguageItem() + override var reloadedAllGamesMessage = LanguageItem("[&9MCTennis&f] Reloaded all games.") - override var reloadedAllGamesMessage: LanguageItem = LanguageItem() + override var reloadedGameMessage = LanguageItem("[&9MCTennis&f] Reloaded game %1$1s.") - override var reloadedGameMessage: LanguageItem = LanguageItem() + override var joinTeamRedMessage = LanguageItem("[&9MCTennis&f] Successfully joined team red.") - override var joinTeamRedMessage: LanguageItem = LanguageItem() + override var joinTeamBlueMessage = LanguageItem("[&9MCTennis&f] Successfully joined team blue.") - override var joinTeamBlueMessage: LanguageItem = LanguageItem() + override var leftGameMessage = LanguageItem("[&9MCTennis&f] Left the game.") - override var leftGameMessage: LanguageItem = LanguageItem() + override var deletedGameMessage = LanguageItem("[&9MCTennis&f] Deleted game %1$1s.") - override var deletedGameMessage: LanguageItem = LanguageItem() + override var notEnoughPlayersMessage = LanguageItem("[&9MCTennis&f] Not enough players! Game start was cancelled.") - override var notEnoughPlayersMessage: LanguageItem = LanguageItem() + override var teamDoesNotExistMessage = LanguageItem("[&9MCTennis&f] Team %1$1s does not exist.") - override var teamDoesNotExistMessage: LanguageItem = LanguageItem() + override var updatedInventoryMessage = LanguageItem("[&9MCTennis&f] Updated inventory of game.") - override var updatedInventoryMessage: LanguageItem = LanguageItem() + override var updatedArmorMessage = LanguageItem("[&9MCTennis&f] Updated armor of game.") - override var updatedArmorMessage: LanguageItem = LanguageItem() + override var secondsRemaining = LanguageItem("[&9MCTennis&f] %1$1s second(s) remaining.") - override var secondsRemaining: LanguageItem = LanguageItem() + override var gameCancelledMessage = LanguageItem("[&9MCTennis&f] Game has been cancelled.") - override var gameCancelledMessage: LanguageItem = LanguageItem() + override var scoreRed = LanguageItem("&c&l%mctennis_game_score%") - override var scoreRed: LanguageItem = LanguageItem() + override var scoreBlue = LanguageItem("&9&l%mctennis_game_score%") - override var scoreBlue: LanguageItem = LanguageItem() + override var winRed = LanguageItem("&c&lTeam Red") - override var winRed: LanguageItem = LanguageItem() + override var winSetRed = LanguageItem("&cTeam Red") - override var winSetRed: LanguageItem = LanguageItem() + override var winBlue = LanguageItem("&9Team Blue") - override var winBlue: LanguageItem = LanguageItem() + override var winSetBlue = LanguageItem("&9Team Blue") - override var winSetBlue: LanguageItem = LanguageItem() + override var winDraw = LanguageItem("&fDraw") - override var winDraw: LanguageItem = LanguageItem() + override var readyMessage = LanguageItem("&6&lReady?") - override var readyMessage: LanguageItem = LanguageItem() + override var bounceOutHologram = LanguageItem("&lOut") - override var bounceOutHologram: LanguageItem = LanguageItem() + override var bounceSecondHologram = LanguageItem("&l2nd Bounce") - override var bounceSecondHologram: LanguageItem = LanguageItem() + override var joinSignLine1 = LanguageItem("&f[&r&lMCTennis&r&f]") - override var joinSignLine1: LanguageItem = LanguageItem() + override var joinSignLine2 = LanguageItem("%mctennis_game_stateDisplayName%") - override var joinSignLine2: LanguageItem = LanguageItem() + override var joinSignLine3 = LanguageItem("%mctennis_game_players%/%mctennis_game_maxPlayers%") - override var joinSignLine3: LanguageItem = LanguageItem() + override var joinSignLine4 = LanguageItem("") - override var joinSignLine4: LanguageItem = LanguageItem() + override var leaveSignLine1 = LanguageItem("&f[&r&lMCTennis&r&f]") - override var leaveSignLine1: LanguageItem = LanguageItem() + override var leaveSignLine2 = LanguageItem("&f&lLeave") - override var leaveSignLine2: LanguageItem = LanguageItem() + override var leaveSignLine3 = LanguageItem("%mctennis_game_players%/%mctennis_game_maxPlayers%") - override var leaveSignLine3: LanguageItem = LanguageItem() + override var leaveSignLine4 = LanguageItem("") - override var leaveSignLine4: LanguageItem = LanguageItem() + override var gameStateJoinAble = LanguageItem("&aJoin") - override var gameStateJoinAble: LanguageItem = LanguageItem() + override var gameStateDisabled = LanguageItem("&4Disabled") - override var gameStateDisabled: LanguageItem = LanguageItem() + override var gameStateRunning = LanguageItem("&1Running") - override var gameStateRunning: LanguageItem = LanguageItem() + override var rightClickOnSignMessage = LanguageItem("RightClick on a sign to convert it into a game sign.") - override var rightClickOnSignMessage: LanguageItem = LanguageItem() + override var signTypeDoesNotExist = LanguageItem("This sign type does not exist.") - override var signTypeDoesNotExist: LanguageItem = LanguageItem() + override var addedSignMessage = LanguageItem("A sign was added to the game.") - override var addedSignMessage: LanguageItem = LanguageItem() + override var commandDescription = LanguageItem("All commands for the MCTennis plugin.") - override var commandDescription: LanguageItem = LanguageItem() + override var commandUsage = LanguageItem("[&9MCTennis&f] Use /mctennis help to see more info about the plugin.") - override var commandUsage: LanguageItem = LanguageItem() + override var maxLength20Characters = LanguageItem("The text length has to be less than 20 characters.") - override var maxLength20Characters: LanguageItem = LanguageItem() + override var commandSenderHasToBePlayer = LanguageItem("The command sender has to be a player!") - override var commandSenderHasToBePlayer: LanguageItem = LanguageItem() + override var freeVersionMessage = LanguageItem("This version of MCTennis does only allow 1 game per server. Go to https://patreon.com/Shynixn for the premium version.") - override var freeVersionMessage: LanguageItem = LanguageItem() + override var commandPlaceHolderMessage = LanguageItem("Evaluated placeholder: %1$1s") - override var commandPlaceHolderMessage: LanguageItem = LanguageItem() - - override var queueTimeOutMessage: LanguageItem = LanguageItem().also { - it.text = "[&9MCTennis&f]&c Not enough players joined in time to start the game." - } + override var queueTimeOutMessage = LanguageItem("[&9MCTennis&f]&c Not enough players joined in time to start the game.") } diff --git a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt index 3fe4be8..f14198e 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt @@ -1,17 +1,20 @@ package com.github.shynixn.mctennis import com.github.shynixn.mccoroutine.bukkit.launch -import com.github.shynixn.mctennis.contract.* +import com.github.shynixn.mctennis.contract.GameService +import com.github.shynixn.mctennis.contract.TennisBallFactory import com.github.shynixn.mctennis.entity.TennisArena -import com.github.shynixn.mctennis.enumeration.PluginDependency +import com.github.shynixn.mctennis.enumeration.PlaceHolder import com.github.shynixn.mctennis.impl.commandexecutor.MCTennisCommandExecutor import com.github.shynixn.mctennis.impl.exception.TennisGameException import com.github.shynixn.mctennis.impl.listener.GameListener import com.github.shynixn.mctennis.impl.listener.PacketListener import com.github.shynixn.mctennis.impl.listener.TennisListener import com.github.shynixn.mcutils.common.Version +import com.github.shynixn.mcutils.common.di.DependencyInjectionModule import com.github.shynixn.mcutils.common.language.reloadTranslation import com.github.shynixn.mcutils.common.physic.PhysicObjectService +import com.github.shynixn.mcutils.common.placeholder.PlaceHolderService import com.github.shynixn.mcutils.common.repository.Repository import com.github.shynixn.mcutils.packet.api.PacketInType import com.github.shynixn.mcutils.packet.api.PacketService @@ -23,13 +26,14 @@ import org.bukkit.plugin.java.JavaPlugin import java.util.logging.Level class MCTennisPlugin : JavaPlugin() { - companion object{ - var language : Language? = null + companion object { + var gameKey = "[game]" + var languageKey = "language" } private val prefix: String = org.bukkit.ChatColor.BLUE.toString() + "[MCTennis] " + org.bukkit.ChatColor.WHITE private var isLoaded = false - private lateinit var module: MCTennisDependencyInjectionModule + private lateinit var module: DependencyInjectionModule /** * Called when this plugin is enabled. @@ -37,7 +41,6 @@ class MCTennisPlugin : JavaPlugin() { override fun onEnable() { Bukkit.getServer().consoleSender.sendMessage(prefix + ChatColor.GREEN + "Loading MCTennis ...") this.saveDefaultConfig() - val versions = if (MCTennisDependencyInjectionModule.areLegacyVersionsIncluded) { listOf( Version.VERSION_1_8_R3, @@ -83,16 +86,17 @@ class MCTennisPlugin : JavaPlugin() { logger.log(Level.INFO, "Loaded NMS version ${Version.serverVersion}.") - // Guice - this.module = MCTennisDependencyInjectionModule(this).build() - this.reloadConfig() - - // Load Language - val mcTennisLanguage = module.getService() - MCTennisPlugin.language = mcTennisLanguage - reloadTranslation(mcTennisLanguage as MCTennisLanguageImpl, MCTennisLanguageImpl::class.java) + // Load MCTennisLanguage + val language = MCTennisLanguageImpl() + reloadTranslation(language) logger.log(Level.INFO, "Loaded language file.") + // Module + this.module = MCTennisDependencyInjectionModule(this, language).build() + + // Register PlaceHolder + PlaceHolder.registerAll(module.getService(), module.getService(), language) + // Register Packet module.getService().registerPacketListening(PacketInType.USEENTITY) @@ -100,16 +104,10 @@ class MCTennisPlugin : JavaPlugin() { Bukkit.getPluginManager().registerEvents(module.getService(), this) Bukkit.getPluginManager().registerEvents(module.getService(), this) Bukkit.getPluginManager().registerEvents(module.getService(), this) - Bukkit.getPluginManager().registerEvents(module.getService(), this) // Register CommandExecutor module.getService() - // Register Dependencies - if (Bukkit.getPluginManager().getPlugin(PluginDependency.GEYSER_SPIGOT.pluginName) != null) { - logger.log(Level.INFO, "Loaded dependency ${PluginDependency.GEYSER_SPIGOT.pluginName}.") - } - // Service dependencies Bukkit.getServicesManager().register( TennisBallFactory::class.java, @@ -122,7 +120,6 @@ class MCTennisPlugin : JavaPlugin() { val plugin = this plugin.launch { - // Load Language // Load Games val gameService = module.getService() try { @@ -152,12 +149,13 @@ class MCTennisPlugin : JavaPlugin() { if (signMeta.tag != null) { val game = gameService.getByName(signMeta.tag!!) if (game != null) { - resolvedText = placeHolderService.replacePlaceHolders(text, null, game) + resolvedText = + placeHolderService.resolvePlaceHolder(text, null, mapOf(gameKey to game.arena.name)) } } if (resolvedText == null) { - resolvedText = placeHolderService.replacePlaceHolders(text) + resolvedText = placeHolderService.resolvePlaceHolder(text, null) } resolvedText diff --git a/src/main/kotlin/com/github/shynixn/mctennis/contract/BedrockService.kt b/src/main/kotlin/com/github/shynixn/mctennis/contract/BedrockService.kt deleted file mode 100644 index eb18f06..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/contract/BedrockService.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.shynixn.mctennis.contract - -import org.bukkit.entity.Player -import org.bukkit.event.Listener - -interface BedrockService : Listener { - /** - * All bedrock players. - */ - val bedRockPlayers: HashSet - - /** - * All java players. - */ - val javaPlayers: HashSet -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/contract/Language.kt b/src/main/kotlin/com/github/shynixn/mctennis/contract/MCTennisLanguage.kt similarity index 97% rename from src/main/kotlin/com/github/shynixn/mctennis/contract/Language.kt rename to src/main/kotlin/com/github/shynixn/mctennis/contract/MCTennisLanguage.kt index c160004..aeb7042 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/contract/Language.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/contract/MCTennisLanguage.kt @@ -3,7 +3,7 @@ package com.github.shynixn.mctennis.contract import com.github.shynixn.mcutils.common.language.LanguageItem import com.github.shynixn.mcutils.common.language.LanguageProvider -interface Language : LanguageProvider { +interface MCTennisLanguage : LanguageProvider { var gameStartingMessage: LanguageItem var gameStartCancelledMessage: LanguageItem diff --git a/src/main/kotlin/com/github/shynixn/mctennis/contract/PlaceHolderService.kt b/src/main/kotlin/com/github/shynixn/mctennis/contract/PlaceHolderService.kt deleted file mode 100644 index 4b11baa..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/contract/PlaceHolderService.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.github.shynixn.mctennis.contract - -import org.bukkit.entity.Player - -interface PlaceHolderService { - /** - * Replaces the placeholders. - */ - fun replacePlaceHolders(text: String, player: Player? = null, game: TennisGame? = null): String -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/entity/TennisBallSettings.kt b/src/main/kotlin/com/github/shynixn/mctennis/entity/TennisBallSettings.kt index bcd0782..359a612 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/entity/TennisBallSettings.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/entity/TennisBallSettings.kt @@ -1,6 +1,5 @@ package com.github.shynixn.mctennis.entity -import com.github.shynixn.mctennis.enumeration.VisibilityType import com.github.shynixn.mcutils.common.EffectTargetType import com.github.shynixn.mcutils.common.command.CommandMeta import com.github.shynixn.mcutils.common.item.Item @@ -83,16 +82,6 @@ class TennisBallSettings { */ var clickCooldown: Int = 2000 - /** - * Slime visibility. - */ - var slimeVisibility: VisibilityType = VisibilityType.BEDROCK - - /** - * Armorstand visiblity. - */ - var armorstandVisibility: VisibilityType = VisibilityType.JAVA - /** * Should the ball collide with water blocks or lava? */ diff --git a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PlaceHolder.kt b/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PlaceHolder.kt index 68d2c61..88e6779 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PlaceHolder.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PlaceHolder.kt @@ -1,32 +1,164 @@ package com.github.shynixn.mctennis.enumeration -enum class PlaceHolder(val fullPlaceHolder: String) { +import com.github.shynixn.mctennis.MCTennisPlugin +import com.github.shynixn.mctennis.contract.GameService +import com.github.shynixn.mctennis.contract.MCTennisLanguage +import com.github.shynixn.mctennis.contract.TennisGame +import com.github.shynixn.mcutils.common.placeholder.PlaceHolderService +import org.bukkit.entity.Player + +enum class PlaceHolder(val text: String, val f: (Player?, TennisGame?, Map?) -> String?) { // Game - GAME_ENABLED("%mctennis_game_isEnabled%"), - GAME_JOINABLE("%mctennis_game_isJoinAble%"), - GAME_STARTED("%mctennis_game_isRunning%"), - GAME_DISPLAYNAME("%mctennis_game_displayName%"), - GAME_RAWSCORETEAMRED("%mctennis_game_rawScoreTeamRed%"), - GAME_RAWSCORETEAMBLUE("%mctennis_game_rawScoreTeamBlue%"), - GAME_SCORE("%mctennis_game_score%"), - GAME_CURRENT_SET("%mctennis_game_currentSet%"), - GAME_WON_SETS_TEAM_RED("%mctennis_game_wonSetsTeamRed%"), - GAME_WON_SETS_TEAM_BLUE("%mctennis_game_wonSetsTeamBlue%"), - GAME_STATE("%mctennis_game_state%"), - GAME_STATE_DISPLAYNAME("%mctennis_game_stateDisplayName%"), - GAME_PLAYER_AMOUNT("%mctennis_game_players%"), - GAME_MAX_PLAYER_AMOUNT("%mctennis_game_maxPlayers%"), + GAME_NAME("%mctennis_game_name_[game]%", { _, game, _ -> game?.arena?.name }), + GAME_DISPLAYNAME("%mctennis_game_displayName_[game]%", { _, game, _ -> game?.arena?.displayName }), + GAME_SUM_MAXPLAYERS("%mctennis_game_maxPlayers_[game]%", { _, game, _ -> + if (game != null) { + (game.arena.maxPlayersPerTeam * 2).toString() + } else { + null + } + }), + GAME_ENABLED("%mctennis_game_isEnabled_[game]%", { _, game, _ -> game?.arena?.isEnabled?.toString() }), + GAME_JOINABLE("%mctennis_game_isJoinAble_[game]%", { _, game, _ -> + if (game != null) { + ((game.gameState == GameState.LOBBY_IDLE || game.gameState == GameState.LOBBY_COUNTDOWN) && !game.isFull()).toString() + } else { + null + } + }), + GAME_STARTED("%mctennis_game_isRunning_[game]%", { _, game, _ -> + if (game != null) { + (game.gameState == GameState.RUNNING_SERVING || game.gameState == GameState.RUNNING_PLAYING).toString() + } else { + null + } + }), + GAME_RAWSCORETEAMRED("%mctennis_game_rawScoreTeamRed_[game]%", { _, game, _ -> game?.teamRedScore?.toString() }), + GAME_RAWSCORETEAMBLUE("%mctennis_game_rawScoreTeamBlue_[game]%", { _, game, _ -> game?.teamBlueScore?.toString() }), + GAME_SCORE("%mctennis_game_score_[game]%", { _, game, _ -> game?.getScoreText() }), + GAME_CURRENT_SET("%mctennis_game_currentSet_[game]%", { _, game, _ -> game?.currentSet?.toString() }), + GAME_WON_SETS_TEAM_RED( + "%mctennis_game_wonSetsTeamRed_[game]%", + { _, game, _ -> game?.teamRedSetScore?.toString() }), + GAME_WON_SETS_TEAM_BLUE( + "%mctennis_game_wonSetsTeamBlue_[game]%", + { _, game, _ -> game?.teamBlueSetScore?.toString() }), + GAME_STATE("%mctennis_game_state%", { _, game, _ -> + if (game != null) { + if (!game.arena.isEnabled) { + "DISABLED" + } else if (game.gameState == GameState.RUNNING_PLAYING || game.gameState == GameState.RUNNING_SERVING || game.gameState == GameState.ENDING) { + "RUNNING" + } else { + "JOINABLE" + } + } else { + null + } + }), + GAME_STATE_DISPLAYNAME("%mctennis_game_stateDisplayName_[game]%", { _, game, context -> + val language = context?.get(MCTennisPlugin.languageKey) as MCTennisLanguage? + if (language != null && game != null) { + if (!game.arena.isEnabled) { + language.gameStateDisabled.text + } else if (game.gameState == GameState.RUNNING_PLAYING || game.gameState == GameState.RUNNING_SERVING || game.gameState == GameState.ENDING) { + language.gameStateRunning.text + } else { + language.gameStateJoinAble.text + } + } else { + null + } + }), + GAME_PLAYER_AMOUNT("%mctennis_game_players_[game]%", { _, game, _ -> + if (game != null) { + (game.teamBluePlayers.size + game.teamRedPlayers.size).toString() + } else { + null + } + }), + // Game (Ball) - GAME_BALL_LOCATION_WORLD("%mctennis_ball_locationWorld%"), - GAME_BALL_LOCATION_X("%mctennis_ball_locationX%"), - GAME_BALL_LOCATION_Y("%mctennis_ball_locationY%"), - GAME_BALL_LOCATION_Z("%mctennis_ball_locationZ%"), - GAME_BALL_LOCATION_YAW("%mctennis_ball_locationYaw%"), - GAME_BALL_LOCATION_PITCH("%mctennis_ball_locationPitch%"), + GAME_BALL_LOCATION_WORLD("%mctennis_ball_locationWorld_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().world!!.name + } else { + "" + } + }), + GAME_BALL_LOCATION_X("%mctennis_ball_locationX_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().x.toString() + } else { + "0" + } + }), + GAME_BALL_LOCATION_Y("%mctennis_ball_locationY_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().y.toString() + } else { + "0" + } + }), + GAME_BALL_LOCATION_Z("%mctennis_ball_locationZ_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().z.toString() + } else { + "0" + } + }), + GAME_BALL_LOCATION_YAW("%mctennis_ball_locationYaw_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().yaw.toString() + } else { + "0" + } + }), + GAME_BALL_LOCATION_PITCH("%mctennis_ball_locationPitch_[game]%", { _, game, _ -> + if (game?.ball != null && !game.ball!!.isDead) { + game.ball!!.getLocation().pitch.toString() + } else { + "0" + } + }), + // Player - PLAYER_ISINGAME("%mctennis_player_isInGame%"), - PLAYER_NAME("%mctennis_player_name%"), + PLAYER_ISINGAME("%mctennis_player_isInGame%", { _, game, _ -> (game != null).toString() }), + PLAYER_NAME("%mctennis_player_name%", { player, _, _ -> player?.name }), + // Player and Game - GAME_ISTEAMREDPLAYER("%mctennis_game_isTeamRedPlayer%"), - GAME_ISTEAMBLUEPLAYER("%mctennis_game_isTeamBluePlayer%"), + GAME_ISTEAMREDPLAYER( + "%mctennis_game_isTeamRedPlayer_[game]%", + { player, game, _ -> game?.teamRedPlayers?.contains(player)?.toString() }), + GAME_ISTEAMBLUEPLAYER( + "%mctennis_game_isTeamBluePlayer_[game]%", + { player, game, _ -> game?.teamBluePlayers?.contains(player)?.toString() }); + + companion object { + /** + * Registers all placeHolder. Overrides previously registered placeholders. + */ + fun registerAll( + placeHolderService: PlaceHolderService, + gameService: GameService, + language: MCTennisLanguage + ) { + for (placeHolder in PlaceHolder.values()) { + placeHolderService.register(placeHolder.text) { player, context -> + val newContext = context.toMutableMap() + newContext[MCTennisPlugin.languageKey] = language + val gameNameReference = newContext[MCTennisPlugin.gameKey] as String? + val game = if (gameNameReference != null) { + gameService.getByName(gameNameReference) + } else if (player != null) { + gameService.getByPlayer(player) + } else { + null + } + + placeHolder.f.invoke(player, game, newContext) + } + } + } + } } diff --git a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PluginDependency.kt b/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PluginDependency.kt deleted file mode 100644 index bbe4853..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/PluginDependency.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.shynixn.mctennis.enumeration - -/** - * Plugin dependency. - */ -enum class PluginDependency( - /** - * Plugin name. - */ - val pluginName: String) { - /** - * PlaceHolderApi plugin. - */ - PLACEHOLDERAPI("PlaceholderAPI"), - - /** - * Geyser - */ - GEYSER_SPIGOT("Geyser-Spigot") -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/VisibilityType.kt b/src/main/kotlin/com/github/shynixn/mctennis/enumeration/VisibilityType.kt deleted file mode 100644 index 01820e7..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/enumeration/VisibilityType.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.shynixn.mctennis.enumeration - -enum class VisibilityType { - NONE, - ALL, - BEDROCK, - JAVA -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt index f6a3d75..152c9df 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt @@ -4,6 +4,7 @@ import com.github.shynixn.mccoroutine.bukkit.CoroutineTimings import com.github.shynixn.mccoroutine.bukkit.launch import com.github.shynixn.mccoroutine.bukkit.minecraftDispatcher import com.github.shynixn.mccoroutine.bukkit.ticks +import com.github.shynixn.mctennis.MCTennisPlugin import com.github.shynixn.mctennis.contract.* import com.github.shynixn.mctennis.entity.PlayerData import com.github.shynixn.mctennis.entity.TeamMetadata @@ -18,6 +19,9 @@ import com.github.shynixn.mcutils.common.ChatColor import com.github.shynixn.mcutils.common.chat.ChatMessageService import com.github.shynixn.mcutils.common.command.CommandMeta import com.github.shynixn.mcutils.common.command.CommandService +import com.github.shynixn.mcutils.common.language.LanguageItem +import com.github.shynixn.mcutils.common.language.sendPluginMessage +import com.github.shynixn.mcutils.common.placeholder.PlaceHolderService import com.github.shynixn.mcutils.common.toLocation import kotlinx.coroutines.delay import org.bukkit.Bukkit @@ -34,7 +38,7 @@ class TennisGameImpl( private val plugin: Plugin, private val commandService: CommandService, private val placeHolderService: PlaceHolderService, - private val language: Language + private val language: MCTennisLanguage ) : TennisGame { private var isDisposed = false private var currentQueueTime = arena.queueTimeOutSec @@ -232,11 +236,10 @@ class TennisGameImpl( if (team == Team.RED) { teamRedScore++ - language.sendMessageToPlayers(language.scoreRed, getPlayers(), player.name) - + sendMessageToPlayers(getPlayers(), language.scoreRed, player.name) } else { teamBlueScore++ - language.sendMessageToPlayers(language.scoreBlue, getPlayers(), player.name) + sendMessageToPlayers(getPlayers(), language.scoreBlue, player.name) } plugin.launch { @@ -261,17 +264,17 @@ class TennisGameImpl( // Wait in lobby. for (i in 0 until arena.timeToStart) { val remaining = arena.timeToStart - i - language.sendMessageToPlayers(language.gameStartingMessage, getPlayers(), remaining) + sendMessageToPlayers(getPlayers(), language.gameStartingMessage, remaining) delay(1000L) if (!arena.isEnabled) { dispose() - language.sendMessageToPlayers(language.gameStartCancelledMessage, getPlayers()) + sendMessageToPlayers(getPlayers(), language.gameStartCancelledMessage) return } if (teamBluePlayers.size < arena.minPlayersPerTeam || teamRedPlayers.size < arena.minPlayersPerTeam) { - language.sendMessageToPlayers(language.notEnoughPlayersMessage, getPlayers()) + sendMessageToPlayers(getPlayers(), language.notEnoughPlayersMessage) gameState = GameState.LOBBY_IDLE queueTimeOut() return @@ -335,15 +338,15 @@ class TennisGameImpl( val remaining = arena.gameTime - i if (remaining == 30) { - language.sendMessageToPlayers(language.secondsRemaining, getPlayers(), 30) + sendMessageToPlayers(getPlayers(), language.secondsRemaining, 30) } if (remaining <= 10) { - language.sendMessageToPlayers(language.secondsRemaining, getPlayers(), remaining) + sendMessageToPlayers(getPlayers(), language.secondsRemaining, remaining) } if (!arena.isEnabled) { - language.sendMessageToPlayers(language.gameCancelledMessage, getPlayers()) + sendMessageToPlayers(getPlayers(),language.gameCancelledMessage) dispose() return } @@ -459,7 +462,7 @@ class TennisGameImpl( ball = tennisBallFactory.createTennisBall(ballspawnpoint.toLocation(), arena.ballSettings, this) delay(500) - language.sendMessageToPlayers(language.readyMessage, getPlayers()) + sendMessageToPlayers(getPlayers(), language.readyMessage) delay(1500) ball!!.setVelocity(Vector(0.0, 0.2, 0.0)) ball!!.allowActions = true @@ -492,12 +495,12 @@ class TennisGameImpl( when (team) { Team.RED -> { teamRedSetScore++ - language.sendMessageToPlayers(language.winSetRed, getPlayers()) + sendMessageToPlayers(getPlayers(), language.winSetRed) } else -> { teamBlueSetScore++ - language.sendMessageToPlayers(language.winSetBlue, getPlayers()) + sendMessageToPlayers(getPlayers(), language.winSetBlue) } } @@ -527,19 +530,19 @@ class TennisGameImpl( private suspend fun winGame(team: Team? = null) { when (team) { null -> { - language.sendMessageToPlayers(language.winDraw, getPlayers()) + sendMessageToPlayers(getPlayers(), language.winDraw) executeCommandsWithPlaceHolder(teamRedPlayers, arena.redTeamMeta.drawCommands) executeCommandsWithPlaceHolder(teamBluePlayers, arena.blueTeamMeta.drawCommands) } Team.RED -> { - language.sendMessageToPlayers(language.winRed, getPlayers()) + sendMessageToPlayers(getPlayers(), language.winRed) executeCommandsWithPlaceHolder(teamRedPlayers, arena.redTeamMeta.winCommands) executeCommandsWithPlaceHolder(teamBluePlayers, arena.blueTeamMeta.looseCommands) } else -> { - language.sendMessageToPlayers(language.winBlue, getPlayers()) + sendMessageToPlayers(getPlayers(), language.winBlue) executeCommandsWithPlaceHolder(teamBluePlayers, arena.blueTeamMeta.winCommands) executeCommandsWithPlaceHolder(teamRedPlayers, arena.redTeamMeta.looseCommands) } @@ -713,8 +716,8 @@ class TennisGameImpl( private fun executeCommandsWithPlaceHolder(players: List, commands: List) { commandService.executeCommands(players, commands) { c, p -> - placeHolderService.replacePlaceHolders( - c, p, this + placeHolderService.resolvePlaceHolder( + c, p, mapOf(MCTennisPlugin.gameKey to this.arena.name) ) } } @@ -734,7 +737,7 @@ class TennisGameImpl( if (currentQueueTime <= 0) { isQueueTimeRunning = false for (player in cachedData.keys.toTypedArray()) { - language.sendMessage(language.queueTimeOutMessage, player) + player.sendPluginMessage(language.queueTimeOutMessage) leave(player) } gameState = GameState.LOBBY_IDLE @@ -745,4 +748,10 @@ class TennisGameImpl( } } } + + private fun sendMessageToPlayers(players: List, languageItem: LanguageItem, vararg params: Any) { + for (player in players) { + player.sendPluginMessage(languageItem, params) + } + } } diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/commandexecutor/MCTennisCommandExecutor.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/commandexecutor/MCTennisCommandExecutor.kt index 0555989..b996b5a 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/commandexecutor/MCTennisCommandExecutor.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/commandexecutor/MCTennisCommandExecutor.kt @@ -2,10 +2,8 @@ package com.github.shynixn.mctennis.impl.commandexecutor import com.github.shynixn.mccoroutine.bukkit.launch import com.github.shynixn.mctennis.MCTennisDependencyInjectionModule -import com.github.shynixn.mctennis.MCTennisLanguageImpl import com.github.shynixn.mctennis.contract.GameService -import com.github.shynixn.mctennis.contract.Language -import com.github.shynixn.mctennis.contract.PlaceHolderService +import com.github.shynixn.mctennis.contract.MCTennisLanguage import com.github.shynixn.mctennis.entity.TeamMetadata import com.github.shynixn.mctennis.entity.TennisArena import com.github.shynixn.mctennis.enumeration.JoinResult @@ -13,16 +11,20 @@ import com.github.shynixn.mctennis.enumeration.LocationType import com.github.shynixn.mctennis.enumeration.Permission import com.github.shynixn.mctennis.enumeration.Team import com.github.shynixn.mctennis.impl.exception.TennisGameException -import com.github.shynixn.mcutils.common.* +import com.github.shynixn.mcutils.common.ChatColor +import com.github.shynixn.mcutils.common.CoroutineExecutor import com.github.shynixn.mcutils.common.chat.ChatMessageService import com.github.shynixn.mcutils.common.command.CommandBuilder import com.github.shynixn.mcutils.common.command.CommandMeta import com.github.shynixn.mcutils.common.command.CommandType import com.github.shynixn.mcutils.common.command.Validator import com.github.shynixn.mcutils.common.language.reloadTranslation +import com.github.shynixn.mcutils.common.language.sendPluginMessage +import com.github.shynixn.mcutils.common.placeholder.PlaceHolderService import com.github.shynixn.mcutils.common.repository.CacheRepository +import com.github.shynixn.mcutils.common.toVector3d +import com.github.shynixn.mcutils.common.translateChatColors import com.github.shynixn.mcutils.sign.SignService -import com.google.inject.Inject import org.bukkit.command.CommandSender import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.entity.Player @@ -30,12 +32,12 @@ import org.bukkit.plugin.Plugin import java.util.* import java.util.logging.Level -class MCTennisCommandExecutor @Inject constructor( +class MCTennisCommandExecutor( private val arenaRepository: CacheRepository, private val gameService: GameService, private val plugin: Plugin, private val signService: SignService, - private val language: Language, + private val language: MCTennisLanguage, private val placeHolderService: PlaceHolderService, chatMessageService: ChatMessageService ) { @@ -243,10 +245,10 @@ class MCTennisCommandExecutor @Inject constructor( subCommand("placeholder") { permission(Permission.EDIT_GAME) builder().argument("placeholder").tabs { listOf("<>") }.execute { sender, placeHolder -> - val evaluatedValue = placeHolderService.replacePlaceHolders(placeHolder) + val evaluatedValue = placeHolderService.resolvePlaceHolder(placeHolder, null) sender.sendMessage(language.commandPlaceHolderMessage.text.format(evaluatedValue)) }.executePlayer({ language.commandSenderHasToBePlayer.text }) { player, placeHolder -> - val evaluatedValue = placeHolderService.replacePlaceHolders(placeHolder, player) + val evaluatedValue = placeHolderService.resolvePlaceHolder(placeHolder, player) player.sendMessage(language.commandPlaceHolderMessage.text.format(evaluatedValue)) } } @@ -268,7 +270,7 @@ class MCTennisCommandExecutor @Inject constructor( private suspend fun createArena(sender: CommandSender, name: String, displayName: String) { if (arenaRepository.getAll().size > 0 && !MCTennisDependencyInjectionModule.areLegacyVersionsIncluded) { - language.sendMessage(language.freeVersionMessage, sender) + sender.sendPluginMessage(language.freeVersionMessage) return } @@ -276,7 +278,7 @@ class MCTennisCommandExecutor @Inject constructor( arena.name = name arena.displayName = displayName arenaRepository.save(arena) - language.sendMessage(language.gameCreatedMessage, sender, name) + sender.sendPluginMessage(language.gameCreatedMessage, name) } private suspend fun deleteArena(sender: CommandSender, arena: TennisArena) { @@ -477,10 +479,10 @@ class MCTennisCommandExecutor @Inject constructor( sender.sendMessage(language.rightClickOnSignMessage.text) signService.addSignByRightClick(sender) { sign -> sign.let { - it.line1 = "%mctennis_lang_joinSignLine1%" - it.line2 = "%mctennis_lang_joinSignLine2%" - it.line3 = "%mctennis_lang_joinSignLine3%" - it.line4 = "%mctennis_lang_joinSignLine4%" + it.line1 = language.joinSignLine1.text + it.line2 = language.joinSignLine2.text + it.line3 = language.joinSignLine3.text + it.line4 = language.joinSignLine4.text it.cooldown = 20 it.update = 40 it.commands = mutableListOf(CommandMeta().also { @@ -503,10 +505,10 @@ class MCTennisCommandExecutor @Inject constructor( sender.sendMessage(language.rightClickOnSignMessage.text) signService.addSignByRightClick(sender) { sign -> sign.let { - it.line1 = "%mctennis_lang_leaveSignLine1%" - it.line2 = "%mctennis_lang_leaveSignLine2%" - it.line3 = "%mctennis_lang_leaveSignLine3%" - it.line4 = "%mctennis_lang_leaveSignLine4%" + it.line1 = language.leaveSignLine1.text + it.line2 = language.leaveSignLine2.text + it.line3 = language.leaveSignLine3.text + it.line4 = language.leaveSignLine4.text it.cooldown = 20 it.update = 40 it.commands = mutableListOf(CommandMeta().also { @@ -541,7 +543,7 @@ class MCTennisCommandExecutor @Inject constructor( if (arena == null) { plugin.reloadConfig() - plugin.reloadTranslation(language as MCTennisLanguageImpl, MCTennisLanguageImpl::class.java) + plugin.reloadTranslation(language) plugin.logger.log(Level.INFO, "Loaded language file.") try { diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/GameListener.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/GameListener.kt index fca281a..67d3988 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/GameListener.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/GameListener.kt @@ -4,14 +4,13 @@ import com.github.shynixn.mccoroutine.bukkit.launch import com.github.shynixn.mctennis.contract.GameService import com.github.shynixn.mctennis.enumeration.GameState import com.github.shynixn.mctennis.event.GameEndEvent -import com.google.inject.Inject import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.plugin.Plugin -class GameListener @Inject constructor(private val gameService: GameService, private val plugin: Plugin) : Listener { +class GameListener (private val gameService: GameService, private val plugin: Plugin) : Listener { /** * Handles leaving state. */ diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/PacketListener.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/PacketListener.kt index c20b349..55dce91 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/PacketListener.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/PacketListener.kt @@ -7,12 +7,11 @@ import com.github.shynixn.mcutils.common.physic.PhysicObjectService import com.github.shynixn.mcutils.packet.api.event.PacketAsyncEvent import com.github.shynixn.mcutils.packet.api.meta.enumeration.InteractionType import com.github.shynixn.mcutils.packet.api.packet.PacketInInteractEntity -import com.google.inject.Inject import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.plugin.Plugin -class PacketListener @Inject constructor( +class PacketListener ( private val physicObjectApi: PhysicObjectService, private val gameService: GameService, private val plugin: Plugin diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/TennisListener.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/TennisListener.kt index 4f55a9c..0f56cf3 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/TennisListener.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/listener/TennisListener.kt @@ -1,7 +1,7 @@ package com.github.shynixn.mctennis.impl.listener import com.github.shynixn.mccoroutine.bukkit.launch -import com.github.shynixn.mctennis.contract.Language +import com.github.shynixn.mctennis.contract.MCTennisLanguage import com.github.shynixn.mctennis.contract.TennisBall import com.github.shynixn.mctennis.contract.TennisGame import com.github.shynixn.mctennis.entity.TennisArena @@ -14,17 +14,16 @@ import com.github.shynixn.mcutils.packet.api.meta.enumeration.EntityType import com.github.shynixn.mcutils.packet.api.packet.PacketOutEntityDestroy import com.github.shynixn.mcutils.packet.api.packet.PacketOutEntityMetadata import com.github.shynixn.mcutils.packet.api.packet.PacketOutEntitySpawn -import com.google.inject.Inject import kotlinx.coroutines.delay import org.bukkit.Location import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.plugin.Plugin -class TennisListener @Inject constructor( +class TennisListener ( private val packetService: PacketService, private val plugin: Plugin, - private val language : Language + private val language : MCTennisLanguage ) : Listener { /** * Handles ground bouncing. diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/ArmorstandEntityComponent.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/ArmorstandEntityComponent.kt index 4e3ed18..4c7074a 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/ArmorstandEntityComponent.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/ArmorstandEntityComponent.kt @@ -19,7 +19,6 @@ class ArmorstandEntityComponent( private val itemService: ItemService, private val ballSettings: TennisBallSettings, val entityId: Int, - private var filteredPlayers: HashSet, private val renderOffsetY : Double ) : PhysicComponent { private var rotation = 0.0 @@ -31,10 +30,6 @@ class ArmorstandEntityComponent( } private fun onPlayerSpawn(player: Player, location: Location) { - if (filteredPlayers.contains(player)) { - return - } - packetService.sendPacketOutEntitySpawn(player, PacketOutEntitySpawn().also { it.entityId = this.entityId it.entityType = EntityType.ARMOR_STAND @@ -56,10 +51,6 @@ class ArmorstandEntityComponent( } private fun onPlayerRemove(player: Player) { - if (filteredPlayers.contains(player)) { - return - } - val outer = this packetService.sendPacketOutEntityDestroy(player, PacketOutEntityDestroy().also { it.entityIds = listOf(outer.entityId) @@ -70,9 +61,6 @@ class ArmorstandEntityComponent( val players = playerComponent.visiblePlayers for (player in players) { - if (filteredPlayers.contains(player)) { - continue - } packetService.sendPacketOutEntityVelocity(player, PacketOutEntityVelocity().also { it.entityId = this.entityId @@ -109,10 +97,6 @@ class ArmorstandEntityComponent( val players = playerComponent.visiblePlayers for (player in players) { - if (filteredPlayers.contains(player)) { - continue - } - packetService.sendPacketOutEntityMetadata(player, PacketOutEntityMetadata().also { it.entityId = this.entityId it.armorStandHeadRotation = EulerAngle(rotation, 0.0, 0.0) diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/SlimeEntityComponent.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/SlimeEntityComponent.kt index 2919fb7..fccc076 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/SlimeEntityComponent.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/physic/SlimeEntityComponent.kt @@ -15,9 +15,7 @@ class SlimeEntityComponent( private val playerComponent: PlayerComponent, private val packetService: PacketService, val entityId: Int, - private val slimeSize: Int, - var filteredPlayers: HashSet - ) : PhysicComponent { + private val slimeSize: Int) : PhysicComponent { init { playerComponent.onSpawnMinecraft.add { player, location -> onPlayerSpawn(player, location) } @@ -32,18 +30,11 @@ class SlimeEntityComponent( it.target = location }) - if (!filteredPlayers.contains(player)) { - packetService.sendPacketOutEntityMetadata(player, PacketOutEntityMetadata().also { - it.entityId = this.entityId - it.slimeSize = this.slimeSize - }) - } else { - packetService.sendPacketOutEntityMetadata(player, PacketOutEntityMetadata().also { - it.entityId = this.entityId - it.slimeSize = this.slimeSize - it.isInvisible = true - }) - } + packetService.sendPacketOutEntityMetadata(player, PacketOutEntityMetadata().also { + it.entityId = this.entityId + it.slimeSize = this.slimeSize + it.isInvisible = true + }) } private fun onPlayerRemove(player: Player) { diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/BedrockServiceImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/BedrockServiceImpl.kt deleted file mode 100644 index 366c2f1..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/BedrockServiceImpl.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.github.shynixn.mctennis.impl.service - -import com.github.shynixn.mccoroutine.bukkit.launch -import com.github.shynixn.mctennis.contract.BedrockService -import com.github.shynixn.mcutils.common.physic.PhysicObjectDispatcher -import com.google.inject.Inject -import org.bukkit.Bukkit -import org.bukkit.entity.Player -import org.bukkit.event.EventHandler -import org.bukkit.event.player.PlayerJoinEvent -import org.bukkit.event.player.PlayerQuitEvent -import org.bukkit.plugin.Plugin -import java.util.logging.Level - -class BedrockServiceImpl @Inject constructor( - private val plugin: Plugin, - private val physicDispatcher: PhysicObjectDispatcher -) : - BedrockService { - /** - * All bedrock players. - */ - override val bedRockPlayers: HashSet = HashSet() - - /** - * All java players. - */ - override val javaPlayers: HashSet = HashSet() - - /** - * Geyser plugin. - */ - private var geyserSpigotPlugin: DependencyGeyserSpigotServiceImpl? = null - - init { - Bukkit.getPluginManager().registerEvents(this, plugin) - - try { - if (Bukkit.getPluginManager().getPlugin("Geyser-Spigot") != null) { - geyserSpigotPlugin = DependencyGeyserSpigotServiceImpl() - } - } catch (e: Exception) { - plugin.logger.log(Level.WARNING, "Cannot load Geyser-Spigot integration.") - } - - Bukkit.getOnlinePlayers().forEach { e -> - plugin.launch(physicDispatcher) { - applyPlayerToGroup(e) - } - } - } - - @EventHandler - fun onPlayerQuitEvent(event: PlayerQuitEvent) { - plugin.launch(physicDispatcher) { - if (javaPlayers.contains(event.player)) { - javaPlayers.remove(event.player) - } - } - } - - @EventHandler - fun onPlayerJoinEvent(event: PlayerJoinEvent) { - plugin.launch(physicDispatcher) { - applyPlayerToGroup(event.player) - } - } - - private fun applyPlayerToGroup(player: Player) { - if (isBedRockPlayer(player)) { - plugin.launch(physicDispatcher) { - bedRockPlayers.add(player) - } - } else { - plugin.launch(physicDispatcher) { - javaPlayers.add(player) - } - } - } - - /** - * Gets if the given player is playing on a bedrock client. - */ - private fun isBedRockPlayer(player: Player): Boolean { - try { - if (geyserSpigotPlugin != null) { - return geyserSpigotPlugin!!.isBedrockPlayer(player) - } - } catch (e: Exception) { - // Sometimes the integration fails. Ignore in this case. - } - - return false - } -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyGeyserSpigotServiceImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyGeyserSpigotServiceImpl.kt deleted file mode 100644 index 68b0ba0..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyGeyserSpigotServiceImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.shynixn.mctennis.impl.service - -import org.bukkit.entity.Player -import org.geysermc.api.Geyser - -class DependencyGeyserSpigotServiceImpl { - - fun isBedrockPlayer(player: Player): Boolean { - val connection = Geyser.api().connectionByUuid(player.uniqueId) - return connection != null - } -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyPlaceholderApiServiceImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyPlaceholderApiServiceImpl.kt deleted file mode 100644 index 935b745..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/DependencyPlaceholderApiServiceImpl.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.github.shynixn.mctennis.impl.service - -import com.github.shynixn.mctennis.contract.GameService -import com.github.shynixn.mctennis.contract.PlaceHolderService -import com.github.shynixn.mctennis.contract.TennisGame -import com.google.inject.Inject -import me.clip.placeholderapi.PlaceholderAPI -import me.clip.placeholderapi.expansion.PlaceholderExpansion -import org.bukkit.entity.Player -import org.bukkit.plugin.Plugin - -class DependencyPlaceholderApiServiceImpl @Inject constructor( - private val plugin: Plugin, - private val gameService: GameService -) : PlaceholderExpansion(), PlaceHolderService { - private var registerd: Boolean = false - private val placeHolderService = PlaceHolderServiceImpl(gameService) - - init { - this.registerListener() - } - - /** - * Registers the placeholder hook if it is not already registered. - */ - fun registerListener() { - if (!registerd) { - this.register() - registerd = true - } - } - - /** - * Gets the expansion version which is the same of the plugin version. - */ - override fun getVersion(): String { - return plugin.description.version - } - - /** - * Gets the expansion author for placeholderapi. - */ - override fun getAuthor(): String { - return plugin.description.authors[0] - } - - /** - * Gets the identifier which is required by placeholderapi to match the placeholder against this plugin. - */ - override fun getIdentifier(): String { - return "mctennis" - } - - /** - * OnPlaceHolder Request - * - * @param player player - * @param s customText - * @return result - */ - override fun onPlaceholderRequest(player: Player?, params: String): String? { - if (params == null) { - return null - } - - val parts = params.split("_") - val finalPart = parts[parts.size - 1] - val newParams = parts.dropLast(1).joinToString("_") - - val selectedGame = gameService.getByName(finalPart) - if (selectedGame != null) { - return placeHolderService.replacePlaceHolders("%mctennis_${newParams}%", player, selectedGame) - } - - if (player != null) { - val otherGame = gameService.getByPlayer(player) - - if (otherGame != null) { - return placeHolderService.replacePlaceHolders( - "%mctennis_${params}%", - player, - otherGame - ) - } else { - return placeHolderService.replacePlaceHolders("%mctennis_${params}%", player, null) - } - } - - return null - } - - /** - * Replaces the placeholders. - */ - override fun replacePlaceHolders(text: String, player: Player?, game: TennisGame?): String { - val replacedInput = placeHolderService.replacePlaceHolders(text, player, game) - return PlaceholderAPI.setPlaceholders(player, replacedInput) - } -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/GameServiceImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/GameServiceImpl.kt index ae74667..fecd054 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/GameServiceImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/GameServiceImpl.kt @@ -2,8 +2,7 @@ package com.github.shynixn.mctennis.impl.service import com.github.shynixn.mctennis.MCTennisDependencyInjectionModule import com.github.shynixn.mctennis.contract.GameService -import com.github.shynixn.mctennis.contract.Language -import com.github.shynixn.mctennis.contract.PlaceHolderService +import com.github.shynixn.mctennis.contract.MCTennisLanguage import com.github.shynixn.mctennis.contract.TennisBallFactory import com.github.shynixn.mctennis.entity.TeamMetadata import com.github.shynixn.mctennis.entity.TennisArena @@ -11,16 +10,16 @@ import com.github.shynixn.mctennis.impl.exception.TennisGameException import com.github.shynixn.mctennis.impl.TennisGameImpl import com.github.shynixn.mcutils.common.chat.ChatMessageService import com.github.shynixn.mcutils.common.command.CommandService +import com.github.shynixn.mcutils.common.placeholder.PlaceHolderService import com.github.shynixn.mcutils.common.repository.Repository import com.github.shynixn.mcutils.sign.SignService -import com.google.inject.Inject import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import java.util.logging.Level import kotlin.math.max import kotlin.math.min -class GameServiceImpl @Inject constructor( +class GameServiceImpl( private val arenaRepository: Repository, private val tennisBallFactory: TennisBallFactory, private val plugin: Plugin, @@ -28,7 +27,7 @@ class GameServiceImpl @Inject constructor( private val signService: SignService, private val chatMessageService: ChatMessageService, private val placeHolderService: PlaceHolderService, - private val language: Language + private val language: MCTennisLanguage ) : GameService { private val games = ArrayList() diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/PlaceHolderServiceImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/PlaceHolderServiceImpl.kt deleted file mode 100644 index 2e829df..0000000 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/PlaceHolderServiceImpl.kt +++ /dev/null @@ -1,181 +0,0 @@ -package com.github.shynixn.mctennis.impl.service - -import com.github.shynixn.mctennis.MCTennisLanguageImpl -import com.github.shynixn.mctennis.MCTennisPlugin -import com.github.shynixn.mctennis.contract.GameService -import com.github.shynixn.mctennis.contract.PlaceHolderService -import com.github.shynixn.mctennis.contract.TennisGame -import com.github.shynixn.mctennis.enumeration.GameState -import com.github.shynixn.mctennis.enumeration.PlaceHolder -import com.github.shynixn.mcutils.common.language.LanguageItem -import com.github.shynixn.mcutils.common.translateChatColors -import com.google.inject.Inject -import org.bukkit.entity.Player - -class PlaceHolderServiceImpl @Inject constructor(private val gameService: GameService) : PlaceHolderService { - private val langPlaceHolderFunctions = HashMap String)>() - private val gamePlayerHolderFunctions = HashMap String)>() - private val gameAndPlayerHolderFunctions = HashMap String)>() - private val playerPlaceHolderFunctions = HashMap String)>() - private val placeHolders = HashMap() - - init { - for (placeHolder in PlaceHolder.values()) { - placeHolders[placeHolder.fullPlaceHolder] = placeHolder - } - - for (field in MCTennisLanguageImpl::class.java.declaredFields) { - field.isAccessible = true - langPlaceHolderFunctions["%mctennis_lang_${field.name}%"] = { (field.get(null) as LanguageItem).text } - } - - // Player - playerPlaceHolderFunctions[PlaceHolder.PLAYER_NAME] = - { p -> p.name } - playerPlaceHolderFunctions[PlaceHolder.PLAYER_ISINGAME] = - { p -> (gameService.getByPlayer(p) != null).toString() } - - // Game - gamePlayerHolderFunctions[PlaceHolder.GAME_ENABLED] = { g -> g.arena.isEnabled.toString() } - gamePlayerHolderFunctions[PlaceHolder.GAME_STARTED] = - { g -> (g.gameState == GameState.RUNNING_SERVING || g.gameState == GameState.RUNNING_PLAYING).toString() } - gamePlayerHolderFunctions[PlaceHolder.GAME_JOINABLE] = - { g -> ((g.gameState == GameState.LOBBY_IDLE || g.gameState == GameState.LOBBY_COUNTDOWN) && !g.isFull()).toString() } - gamePlayerHolderFunctions[PlaceHolder.GAME_DISPLAYNAME] = { g -> g.arena.displayName } - gamePlayerHolderFunctions[PlaceHolder.GAME_RAWSCORETEAMRED] = { g -> g.teamRedScore.toString() } - gamePlayerHolderFunctions[PlaceHolder.GAME_RAWSCORETEAMBLUE] = { g -> g.teamBlueScore.toString() } - gamePlayerHolderFunctions[PlaceHolder.GAME_SCORE] = { g -> g.getScoreText() } - gamePlayerHolderFunctions[PlaceHolder.GAME_STATE] = { g -> - if (!g.arena.isEnabled) { - "DISABLED" - } else if (g.gameState == GameState.RUNNING_PLAYING || g.gameState == GameState.RUNNING_SERVING || g.gameState == GameState.ENDING) { - "RUNNING" - } else { - "JOINABLE" - } - - } - gamePlayerHolderFunctions[PlaceHolder.GAME_STATE_DISPLAYNAME] = { g -> - if (!g.arena.isEnabled) { - MCTennisPlugin.language!!.gameStateDisabled.text - } else if (g.gameState == GameState.RUNNING_PLAYING || g.gameState == GameState.RUNNING_SERVING || g.gameState == GameState.ENDING) { - MCTennisPlugin.language!!.gameStateRunning.text - } else { - MCTennisPlugin.language!!.gameStateJoinAble.text - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_PLAYER_AMOUNT] = { g -> - (g.teamBluePlayers.size + g.teamRedPlayers.size).toString() - } - gamePlayerHolderFunctions[PlaceHolder.GAME_MAX_PLAYER_AMOUNT] = { g -> - (g.arena.maxPlayersPerTeam * 2).toString() - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_WORLD] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().world!!.name - } else { - "" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_X] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().x.toString() - } else { - "0" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_Y] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().y.toString() - } else { - "-1000" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_Z] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().z.toString() - } else { - "0" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_YAW] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().yaw.toString() - } else { - "0" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_BALL_LOCATION_PITCH] = { g -> - if (g.ball != null && !g.ball!!.isDead) { - g.ball!!.getLocation().pitch.toString() - } else { - "0" - } - } - gamePlayerHolderFunctions[PlaceHolder.GAME_CURRENT_SET] = { g -> - g.currentSet.toString() - } - gamePlayerHolderFunctions[PlaceHolder.GAME_WON_SETS_TEAM_BLUE] = { g -> - g.teamBlueSetScore.toString() - } - gamePlayerHolderFunctions[PlaceHolder.GAME_WON_SETS_TEAM_RED] = { g -> - g.teamRedSetScore.toString() - } - - // Game and Player - gameAndPlayerHolderFunctions[PlaceHolder.GAME_ISTEAMBLUEPLAYER] = - { g, p -> g.teamBluePlayers.contains(p).toString() } - gameAndPlayerHolderFunctions[PlaceHolder.GAME_ISTEAMREDPLAYER] = - { g, p -> g.teamRedPlayers.contains(p).toString() } - } - - /** - * Replaces the placeholders. - */ - override fun replacePlaceHolders(text: String, player: Player?, game: TennisGame?): String { - var output = text - for (i in 0 until 4) { - if (!output.contains("%")) { - break - } - - val locatedPlaceHolders = HashMap() - val characterCache = StringBuilder() - - for (character in output) { - characterCache.append(character) - - if (character == '%') { - val evaluatedPlaceHolder = characterCache.toString() - if (placeHolders.containsKey(evaluatedPlaceHolder)) { - val placeHolder = placeHolders[evaluatedPlaceHolder]!! - if (!locatedPlaceHolders.containsKey(placeHolder.fullPlaceHolder)) { - if (game != null && player != null && gameAndPlayerHolderFunctions.containsKey(placeHolder)) { - locatedPlaceHolders[placeHolder.fullPlaceHolder] = - gameAndPlayerHolderFunctions[placeHolder]!!.invoke(game, player) - } else if (game != null && gamePlayerHolderFunctions.containsKey(placeHolder)) { - locatedPlaceHolders[placeHolder.fullPlaceHolder] = - gamePlayerHolderFunctions[placeHolder]!!.invoke(game) - } else if (player != null && playerPlaceHolderFunctions.containsKey(placeHolder)) { - locatedPlaceHolders[placeHolder.fullPlaceHolder] = - playerPlaceHolderFunctions[placeHolder]!!.invoke(player) - } - } - } else if (langPlaceHolderFunctions.containsKey(evaluatedPlaceHolder)) { - locatedPlaceHolders[evaluatedPlaceHolder] = - langPlaceHolderFunctions[evaluatedPlaceHolder]!!.invoke() - } - - characterCache.clear() - characterCache.append(character) - } - } - - for (locatedPlaceHolder in locatedPlaceHolders.keys) { - output = output.replace(locatedPlaceHolder, locatedPlaceHolders[locatedPlaceHolder]!!) - } - } - - return output.translateChatColors() - } -} diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/TennisBallFactoryImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/TennisBallFactoryImpl.kt index e71884e..6ac18a5 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/service/TennisBallFactoryImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/service/TennisBallFactoryImpl.kt @@ -2,7 +2,6 @@ package com.github.shynixn.mctennis.impl.service import com.github.shynixn.mctennis.contract.* import com.github.shynixn.mctennis.entity.TennisBallSettings -import com.github.shynixn.mctennis.enumeration.VisibilityType import com.github.shynixn.mctennis.impl.TennisBallImpl import com.github.shynixn.mctennis.entity.MathSettings import com.github.shynixn.mctennis.impl.physic.* @@ -12,15 +11,13 @@ import com.github.shynixn.mcutils.common.sound.SoundService import com.github.shynixn.mcutils.common.toVector3d import com.github.shynixn.mcutils.packet.api.PacketService import com.github.shynixn.mcutils.packet.api.RayTracingService -import com.google.inject.Inject import org.bukkit.Location import org.bukkit.plugin.Plugin -class TennisBallFactoryImpl @Inject constructor( +class TennisBallFactoryImpl( private val physicObjectService: PhysicObjectService, private val plugin: Plugin, private val soundService: SoundService, - private val bedrockService: BedrockService, private val packetService: PacketService, private val rayTracingService: RayTracingService, private val itemService: ItemService @@ -51,90 +48,23 @@ class TennisBallFactoryImpl @Inject constructor( val armorStandEntityId = packetService.getNextEntityId() val slimeEntityId = packetService.getNextEntityId() - val armorstandEntityComponent = when (settings.armorstandVisibility) { - VisibilityType.BEDROCK -> { - ArmorstandEntityComponent( - mathPhysicComponent, - packetService, - playerComponent, - itemService, - settings, - armorStandEntityId, - bedrockService.javaPlayers, - settings.renderYOffset - ) - } - VisibilityType.JAVA -> { - ArmorstandEntityComponent( - mathPhysicComponent, - packetService, - playerComponent, - itemService, - settings, - armorStandEntityId, - bedrockService.bedRockPlayers, - settings.renderYOffset - ) - } - VisibilityType.ALL -> { - ArmorstandEntityComponent( - mathPhysicComponent, - packetService, - playerComponent, - itemService, - settings, - armorStandEntityId, - hashSetOf(), - settings.renderYOffset - ) - } - else -> { - null - } - } + val armorstandEntityComponent = ArmorstandEntityComponent( + mathPhysicComponent, + packetService, + playerComponent, + itemService, + settings, + armorStandEntityId, + settings.renderYOffset + ) - val slimeEntityComponent = when (settings.slimeVisibility) { - VisibilityType.BEDROCK -> { - SlimeEntityComponent( - mathPhysicComponent, - playerComponent, - packetService, - slimeEntityId, - settings.clickHitBoxSize, - bedrockService.javaPlayers - ) - } - VisibilityType.JAVA -> { - SlimeEntityComponent( - mathPhysicComponent, - playerComponent, - packetService, - slimeEntityId, - settings.clickHitBoxSize, - bedrockService.bedRockPlayers - ) - } - VisibilityType.ALL -> { - SlimeEntityComponent( - mathPhysicComponent, - playerComponent, - packetService, - slimeEntityId, - settings.clickHitBoxSize, - hashSetOf() - ) - } - else -> { - SlimeEntityComponent( - mathPhysicComponent, - playerComponent, - packetService, - slimeEntityId, - settings.clickHitBoxSize, - hashSetOf() - ) - } - } + val slimeEntityComponent = SlimeEntityComponent( + mathPhysicComponent, + playerComponent, + packetService, + slimeEntityId, + settings.clickHitBoxSize + ) val ball = TennisBallImpl( mathPhysicComponent, diff --git a/src/main/resources/arena_sample.yml b/src/main/resources/arena_sample.yml index fa9f8d4..d7c3b1c 100644 --- a/src/main/resources/arena_sample.yml +++ b/src/main/resources/arena_sample.yml @@ -244,11 +244,6 @@ ball: clickHitBoxSize: 3 # Cooldown in Milliseconds how often the ball can be touched. clickCooldown: 2000 - # Flag if the slime hitbox should be shown on "BEDROCK", "JAVA" or "ALL". - slimeVisibility: "BEDROCK" - # Flag if the armorstand ball should be shown on "BEDROCK", "JAVA" or "ALL". - # Note, Armorstand blocks are invisible on Bedrock, which is a limitation of bedrock itself. - armorstandVisibility: "JAVA" # Commands which are executed every MCTennis game tick (1 tick per second, not the minecraft tick which is 20 ticks per second) # Types are: # SERVER (executes a single command with server level permission) diff --git a/storage/court.yml b/storage/court.yml index 67e1e71..d1ab946 100644 --- a/storage/court.yml +++ b/storage/court.yml @@ -106,8 +106,6 @@ ball: spinDefault: 20.0 spinVertical: 0.6 clickCooldown: 250 - slimeVisibility: "BEDROCK" - armorstandVisibility: "JAVA" hitSound: name: "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR,ENTITY_ZOMBIE_ATTACK_DOOR_WOOD,ZOMBIE_WOOD" volume: 5.0 From e98aacb8deb6652db155e1701c22040b7328c390 Mon Sep 17 00:00:00 2001 From: Shynixn Date: Fri, 24 Jan 2025 15:04:46 +0100 Subject: [PATCH 2/5] Fixed github build. --- .github/workflows/main.yml | 20 +++++++++++++++++++- README.md | 7 ++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e459084..fc809a6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,12 +25,19 @@ jobs: - name: Build Java Application env: - SHYNIXN_MCUTILS_REPOSITORY: ${{ secrets.SHYNIXN_MCUTILS_REPOSITORY }} + SHYNIXN_MCUTILS_REPOSITORY_2025: ${{ secrets.SHYNIXN_MCUTILS_REPOSITORY_2025 }} run: | chmod +x gradlew ./gradlew build pluginJars echo "RELEASE_VERSION=$(./gradlew -q printVersion)" >> $GITHUB_ENV + - name: Create Geyser Customizations + if: "contains(github.event.head_commit.message, '--release') && contains(github.ref, 'main')" + env: + GEYSER_PASSWORD: ${{ secrets.GEYSER_PASSWORD }} + run: | + 7z x docs/resources/MCTennis-GeyserMC.7z -p${{ env.GEYSER_PASSWORD }} + - name: Create Github Release if: "contains(github.event.head_commit.message, '--release') && contains(github.ref, 'main')" id: create_release @@ -77,6 +84,17 @@ jobs: asset_name: MCTennis-Legacy.jar asset_content_type: application/jar + - name: Geyser Customizations to Github + if: "contains(github.event.head_commit.message, '--release') && contains(github.ref, 'main')" + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: /home/runner/work/MCTennis/MCTennis/MCTennis-GeyserMC.zip + asset_name: MCTennis-GeyserMC.zip + asset_content_type: application/zip + Wiki: runs-on: ubuntu-latest if: "contains(github.ref, 'main')" diff --git a/README.md b/README.md index e60a0a6..e53ad7d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # MCTennis -| branch | status | download | -|--------|----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| main | [![Build Status](https://github.com/Shynixn/MCTennis/workflows/CI/badge.svg?branch=main)](https://github.com/Shynixn/MCTennis
/actions) | [Download latest release](https://github.com/Shynixn/MCtennis/releases) | +| branch | status | download | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| +| main | [![Build Status](https://github.com/Shynixn/MCTennis/actions/workflows/main.yml/badge.svg)](https://github.com/Shynixn/MCTennis/actions) | [Download latest release](https://github.com/Shynixn/MCtennis/releases) | +| development | [![Build Status](https://github.com/Shynixn/MCTennis/actions/workflows/main.yml/badge.svg?branch=development)](https://github.com/Shynixn/MCTennis/actions) | | ## Description From a50bc64c140792f200955b7de4ae5b1db9d1d403 Mon Sep 17 00:00:00 2001 From: Shynixn Date: Fri, 24 Jan 2025 16:44:52 +0100 Subject: [PATCH 3/5] #71 Added support for bedrock. --- docs/resources/MCTennis-GeyserMC.7z | Bin 0 -> 36754 bytes docs/wiki/docs/bedrock.md | 35 ++++++++++++++++++++++++++++ docs/wiki/mkdocs.yml | 1 + 3 files changed, 36 insertions(+) create mode 100644 docs/resources/MCTennis-GeyserMC.7z create mode 100644 docs/wiki/docs/bedrock.md diff --git a/docs/resources/MCTennis-GeyserMC.7z b/docs/resources/MCTennis-GeyserMC.7z new file mode 100644 index 0000000000000000000000000000000000000000..e705506fa856260ea6c84b64c9c96fa62bcf3111 GIT binary patch literal 36754 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ß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 K03ZMW0001(GcPIt literal 0 HcmV?d00001 diff --git a/docs/wiki/docs/bedrock.md b/docs/wiki/docs/bedrock.md new file mode 100644 index 0000000..a153b27 --- /dev/null +++ b/docs/wiki/docs/bedrock.md @@ -0,0 +1,35 @@ +# Bedrock + +MCTennis supports crossplay with Bedrock clients (SmartPhone,Windows,Console, etc.) using [GeyserMC](https://geysermc.org/). + +### Initial Setup + +* Install [GeyserMC](https://geysermc.org/) on your server or on your proxy server. +* Install MCTennis on your Spigot/Paper based server +* Join your server with a BedRock client and join the MCTennis game ``/mctennis join game1``. +* Observe that the ball will be displayed as a simple player_head because bedrock does not support custom player heads. +* Observe, that the ball will not be able to rotate. + +### Fixing skin and rotations via GeyserMC (PatreonOnly) + +Thanks to my **Patreon supporters**, who have funded this feature :heart: . +They can download my [prepared zip file](https://www.patreon.com/Shynixn) to easily setup MCTennis for Bedrock. + +If you are using the free version of MCTennis, you can still configure MCTennis for Bedrock, but it is more work for you. If you want +to save time, become a patreon member at [https://www.patreon.com/Shynixn](https://www.patreon.com/Shynixn). + +=== "Spigot/Paper" + + * Download the ``MCTennis-GeyserMC.zip`` file from [https://www.patreon.com/Shynixn](https://www.patreon.com/Shynixn). + * Extract the ``MCTennis-GeyserMC.zip`` contents into your ``plugins\Geyser-Spigot``. + * Extract the ``custom-skulls_mctennis.yml`` into ``plugins\Geyser-Spigot\custom-skulls_mctennis.yml`` + * Extract the ``packs/MCTennisPack.mcpack`` into ``plugins\Geyser-Spigot\packs\MCTennisPack.mcpack`` + * Copy the ``player-profiles`` values from ``plugins\Geyser-Spigot\custom-skulls_mctennis.yml`` into the ``plugins\Geyser-Spigot\custom-skulls.yml`` file. + +=== "Proxies (BungeeCord, Velocity, etc.)" + + * Download the ``MCTennis-GeyserMC.zip`` file from [https://www.patreon.com/Shynixn](https://www.patreon.com/Shynixn). + * Extract the ``MCTennis-GeyserMC.zip`` contents into your ``plugins\Geyser-``. + * Extract the ``custom-skulls_mctennis.yml`` into ``plugins\Geyser-\custom-skulls_mctennis.yml`` + * Extract the ``packs/MCTennisPack.mcpack`` into ``plugins\Geyser-\packs\MCTennisPack.mcpack`` + * Copy the ``player-profiles`` values from ``plugins\Geyser-\custom-skulls_mctennis.yml`` into the ``plugins\Geyser-\custom-skulls.yml`` file. diff --git a/docs/wiki/mkdocs.yml b/docs/wiki/mkdocs.yml index 3267f32..b57a225 100644 --- a/docs/wiki/mkdocs.yml +++ b/docs/wiki/mkdocs.yml @@ -7,6 +7,7 @@ nav: - Permission: permission.md - Creating the game: game.md - Interactions: interaction.md + - Bedrock: bedrock.md - Commands: commands.md - PlaceHolders: placeholders.md - Developer Api: api.md From 943fbc734de5d7636095fa8b54dc4876a9e8444a Mon Sep 17 00:00:00 2001 From: Shynixn Date: Fri, 24 Jan 2025 16:46:08 +0100 Subject: [PATCH 4/5] #72 Added support for the duration property in language files. --- build.gradle.kts | 4 ++-- src/main/resources/lang/en_us.yml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 715a6d2..8a17028 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,8 +29,8 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") // Custom dependencies - implementation("com.github.shynixn.mcutils:common:2025.1") - implementation("com.github.shynixn.mcutils:packet:2025.1") + implementation("com.github.shynixn.mcutils:common:2025.3") + implementation("com.github.shynixn.mcutils:packet:2025.2") implementation("com.github.shynixn.mcutils:sign:2025.1") } diff --git a/src/main/resources/lang/en_us.yml b/src/main/resources/lang/en_us.yml index c970f53..d2b21b8 100644 --- a/src/main/resources/lang/en_us.yml +++ b/src/main/resources/lang/en_us.yml @@ -4,6 +4,8 @@ gameStartingMessage: type: "CHAT" # The primary text to be sent. text: "[&9MCTennis&f] Game is starting in %1$1d seconds." + # Only available for type "ACTIONBAR". The time until the action bar message disappears. + durationInTicks: 60 # Only available for type "TITLE". Adds a subTitle. subTitle: "" # Only available for type: "TITLE". Adds a fade in effect. From 9c3342c2fc027376735b2f513d1c5fff964484e0 Mon Sep 17 00:00:00 2001 From: Shynixn Date: Fri, 24 Jan 2025 17:12:44 +0100 Subject: [PATCH 5/5] #74 Updated to release version. --- build.gradle.kts | 6 ++-- docs/wiki/docs/sign.md | 31 +++++++++++++++++++ docs/wiki/mkdocs.yml | 1 + .../shynixn/mctennis/MCTennisLanguageImpl.kt | 2 +- .../github/shynixn/mctennis/MCTennisPlugin.kt | 4 +-- .../shynixn/mctennis/impl/TennisGameImpl.kt | 15 ++++++--- src/main/resources/plugin-legacy.yml | 2 +- src/main/resources/plugin.yml | 5 +-- 8 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 docs/wiki/docs/sign.md diff --git a/build.gradle.kts b/build.gradle.kts index 8a17028..1da4cb8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "com.github.shynixn" -version = "1.13.0" +version = "1.14.0" repositories { mavenLocal() @@ -30,7 +30,7 @@ dependencies { // Custom dependencies implementation("com.github.shynixn.mcutils:common:2025.3") - implementation("com.github.shynixn.mcutils:packet:2025.2") + implementation("com.github.shynixn.mcutils:packet:2025.3") implementation("com.github.shynixn.mcutils:sign:2025.1") } @@ -207,7 +207,7 @@ tasks.register("languageFile") { implContents.add("") implContents.add("class MCTennisLanguageImpl : MCTennisLanguage {") implContents.add(" override val names: List\n" + - " get() = listOf(\"en_us\", \"es_es\", \"zh_cn\")") + " get() = listOf(\"en_us\")") for (i in 0 until lines.size) { val key = lines[i] diff --git a/docs/wiki/docs/sign.md b/docs/wiki/docs/sign.md new file mode 100644 index 0000000..95c1f7d --- /dev/null +++ b/docs/wiki/docs/sign.md @@ -0,0 +1,31 @@ +# Signs + +This page explains how to create signs for joining and leave. + +### Create a join sign + +* Place a new sign in your world +* Execute the following command: + +``` +/mctennis sign game1 join +``` + +* Rightclick on a sign +* This sign simply executes the ``/mctennis join`` command on behalf of the player. You can create team join signs by searching for the created sign in your ``game1.yml`` and editing the command to e.g. ``/mctennis join red`` + +### Create a leave sign + +* Place a new sign in your world +* Execute the following command: + +``` +/mctennis sign game1 leave +``` + +* Rightclick on a sign +* This sign simply executes the ``/mctennis leave`` command on behalf of the player. + +### Removing a sign + +* Simply destroy the sign with your hand diff --git a/docs/wiki/mkdocs.yml b/docs/wiki/mkdocs.yml index b57a225..abf08a3 100644 --- a/docs/wiki/mkdocs.yml +++ b/docs/wiki/mkdocs.yml @@ -7,6 +7,7 @@ nav: - Permission: permission.md - Creating the game: game.md - Interactions: interaction.md + - Signs: sign.md - Bedrock: bedrock.md - Commands: commands.md - PlaceHolders: placeholders.md diff --git a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt index 269718e..bb8575e 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisLanguageImpl.kt @@ -5,7 +5,7 @@ import com.github.shynixn.mctennis.contract.MCTennisLanguage class MCTennisLanguageImpl : MCTennisLanguage { override val names: List - get() = listOf("en_us", "es_es", "zh_cn") + get() = listOf("en_us") override var gameStartingMessage = LanguageItem("[&9MCTennis&f] Game is starting in %1$1d seconds.") override var gameStartCancelledMessage = LanguageItem("[&9MCTennis&f] Game start has been cancelled.") diff --git a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt index f14198e..7c8eb02 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/MCTennisPlugin.kt @@ -111,12 +111,12 @@ class MCTennisPlugin : JavaPlugin() { // Service dependencies Bukkit.getServicesManager().register( TennisBallFactory::class.java, - module.getService(), + module.getService(), this, ServicePriority.Normal ) Bukkit.getServicesManager() - .register(GameService::class.java, module.getService(), this, ServicePriority.Normal) + .register(GameService::class.java, module.getService(), this, ServicePriority.Normal) val plugin = this plugin.launch { diff --git a/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt b/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt index 152c9df..9162617 100644 --- a/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt +++ b/src/main/kotlin/com/github/shynixn/mctennis/impl/TennisGameImpl.kt @@ -5,7 +5,10 @@ import com.github.shynixn.mccoroutine.bukkit.launch import com.github.shynixn.mccoroutine.bukkit.minecraftDispatcher import com.github.shynixn.mccoroutine.bukkit.ticks import com.github.shynixn.mctennis.MCTennisPlugin -import com.github.shynixn.mctennis.contract.* +import com.github.shynixn.mctennis.contract.MCTennisLanguage +import com.github.shynixn.mctennis.contract.TennisBall +import com.github.shynixn.mctennis.contract.TennisBallFactory +import com.github.shynixn.mctennis.contract.TennisGame import com.github.shynixn.mctennis.entity.PlayerData import com.github.shynixn.mctennis.entity.TeamMetadata import com.github.shynixn.mctennis.entity.TennisArena @@ -346,7 +349,7 @@ class TennisGameImpl( } if (!arena.isEnabled) { - sendMessageToPlayers(getPlayers(),language.gameCancelledMessage) + sendMessageToPlayers(getPlayers(), language.gameCancelledMessage) dispose() return } @@ -749,9 +752,13 @@ class TennisGameImpl( } } - private fun sendMessageToPlayers(players: List, languageItem: LanguageItem, vararg params: Any) { + private fun sendMessageToPlayers(players: List, languageItem: LanguageItem, param: Any? = null) { for (player in players) { - player.sendPluginMessage(languageItem, params) + if (param != null) { + player.sendPluginMessage(languageItem, param) + } else { + player.sendPluginMessage(languageItem) + } } } } diff --git a/src/main/resources/plugin-legacy.yml b/src/main/resources/plugin-legacy.yml index 6b240f3..cc7d8ec 100644 --- a/src/main/resources/plugin-legacy.yml +++ b/src/main/resources/plugin-legacy.yml @@ -1,5 +1,5 @@ name: MCTennis -version: 1.13.0 +version: 1.14.0 author: Shynixn website: https://www.spigotmc.org/members/shynixn.63455/ main: com.github.shynixn.mctennis.MCTennisPlugin diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 830e172..8be0ed7 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: MCTennis -version: 1.13.0 +version: 1.14.0 author: Shynixn website: https://www.spigotmc.org/members/shynixn.63455/ main: com.github.shynixn.mctennis.MCTennisPlugin @@ -8,8 +8,5 @@ api-version: 1.13 libraries: - com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:2.20.0 - com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:2.20.0 - - com.google.inject:guice:7.0.0 - - com.google.code.gson:gson:2.10.1 - org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.25 - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 - - aopalliance:aopalliance:1.0