v2.4.1 merge from upstream

This commit is contained in:
NotAlexNoyle committed 2026-03-23 06:54:30 -04:00
commit c57e22fd22
43 files changed
+676 -601

No files matched your search

-2
View File
@@ -1,2 +0,0 @@
* @EternalCodeTeam/eternalcodeteam-maintainers
/.github/CODEOWNERS @EternalCodeTeam/eternalcodeteam-maintainers
-128
View File
@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://discord.gg/FQ7jmGBd6c.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
-36
View File
@@ -1,36 +0,0 @@
# Contributing to EternalCombat
We welcome all contributions to the EternalCombat project!
### How to Contribute
1. Fork the repository.
2. Create a new branch for your feature or bug fix.
3. Make your changes, and test them thoroughly.
4. Commit your changes and push them to your fork.
5. Submit a pull request to the main repository.
### Code of Conduct
We expect all contributors to follow our [code of conduct](CODE_OF_CONDUCT.md).
### Reporting Issues
If you find an issue with the plugin, please report it in
the [Issues tab](https://github.com/EternalCodeTeam/EternalCombat/issues). Please provide as much information as
possible, including the version of Minecraft and the plugin you are using, as well as any error messagesSettings or logs.
### Compatibility
CombatLog has been tested on versions 1.17.1 - 1.19.3, but probably works on most versions of Minecraft. If you find
compatibility issues, please report them in the Issues tab. CombatLog uses java 11+, so you need to have it installed on
your server.
### Submitting a Pull Request
When submitting a pull request, please make sure to follow these guidelines:
- Make sure that your code adheres to the plugin's existing coding style.
- Test your changes thoroughly before submitting the pull request.
- If your pull request is related to an existing issue, please reference the issue in your pull request.
- Thank you for your contributions to the EternalCombat project!
-33
View File
@@ -1,33 +0,0 @@
---
name: Bug report
about: Create a bug report to help us improve EternalCombat <3
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Platform (please complete the following information):**
- Java Version: [e.g. JDK Temurin 17]
- Server software, ex. PaperMC 1.19.3 build #1
**Additional notes**
Add any other context about the problem here.
-20
View File
@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for EternalCombat <3
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
-1
View File
@@ -1 +0,0 @@
**Please describe the changes made by this PR and why they need to be merged:**
-42
View File
@@ -1,42 +0,0 @@
name: Java CI with Gradle
on:
push:
branches: [ "master" ]
pull_request:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: >-
${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*',
'**/gradle-wrapper.properties') }}
restore-keys: '${{ runner.os }}-gradle-'
- name: Make gradlew executable
run: chmod +x gradlew
- name: Build with Gradle
uses: gradle/gradle-build-action@093dfe9d598ec5a42246855d09b49dc76803c005
with:
arguments: shadowJar
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
name: 'Successfully build EternalCombat'
path: eternalcombat-plugin/build/libs/*.jar
-28
View File
@@ -1,28 +0,0 @@
name: Publish EternalCombat API
on:
release:
branches: [ master ]
types: [ published ]
jobs:
publish:
runs-on: ubuntu-latest
environment: deployment
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
cache: 'gradle'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Publish with Gradle
run: ./gradlew clean build eternalcombat-api:publish
env:
ETERNAL_CODE_MAVEN_USERNAME: ${{ secrets.ETERNAL_CODE_MAVEN_USERNAME }}
ETERNAL_CODE_MAVEN_PASSWORD: ${{ secrets.ETERNAL_CODE_MAVEN_PASSWORD }}
+20 -11
View File
@@ -9,6 +9,15 @@
[![Chat on Discord](https://raw.githubusercontent.com/vLuckyyy/badges/main//chat-with-us-on-discord.svg)](https://discord.com/invite/FQ7jmGBd6c)
[![Read the Docs](https://raw.githubusercontent.com/vLuckyyy/badges/main/read-the-documentation.svg)](https://docs.eternalcode.pl/eternalcombat/introduction)
[![Available on BStats](https://raw.githubusercontent.com/vLuckyyy/badges/main/available-on-bstats.svg)](https://bstats.org/plugin/bukkit/EternalCombat/17803)
[Report Bug](https://github.com/EternalCodeTeam/EternalCombat/issues) • [Request Feature](https://github.com/EternalCodeTeam/EternalCombat/issues) • [Join Discord](https://discord.gg/eternalcode)
<br>
<a href="https://ko-fi.com/eternalcodeteam">
<img src="https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/donate/kofi-plural-alt_64h.png?raw=true" height="64" alt="Support us on Ko-fi">
</a>
</div>
### Information
@@ -16,7 +25,7 @@
## EternalCombat requires PacketEvents plugin to work.
You can download it from [here](https://modrinth.com/plugin/packetevents)
EternalCombat 2.0 has been tested on Minecraft versions **1.17.1 to 1.21.8**, but it should work seamlessly on most
EternalCombat 2.0 has been tested on Minecraft versions **1.17.1 to 1.21.11**, but it should work seamlessly on most
other versions too.
If you run into any compatibility issues, please let us know in
the [Issues tab](https://github.com/EternalCodeTeam/EternalCombat/issues).
@@ -68,14 +77,14 @@ EternalCombat in full swing and learn why it’s a game-changer for your server!
Control who can use EternalCombat’s powerful features with these permissions:
| Permission | Description |
|--------------------------------|--------------------------------------------------------------------------|
| `eternalcombat.status` | Check a player’s combat status with `/combatlog status <player>`. |
| `eternalcombat.tag` | Start a fight between players using `/combatlog tag <player> [player2]`. |
| `eternalcombat.untag` | Remove a player from combat with `/combatlog untag <player>`. |
| `eternalcombat.reload` | Reload the plugin with `/combatlog reload`. |
| `eternalcombat.receiveupdates` | Receive notifications about new plugin versions on join. |
| `eternalcombat.bypass` | Bypass combat tagging, need's `excludeAdminsFromCombat` to be enabled |
| Permission | Description |
|--------------------------------|-------------------------------------------------------------------------------------------------------|
| `eternalcombat.status` | Check a player’s combat status with `/combatlog status <player>`. |
| `eternalcombat.tag` | Start a fight between players using `/combatlog tag <player> [player2]`. |
| `eternalcombat.untag` | Remove a player from combat with `/combatlog untag <player>`. |
| `eternalcombat.reload` | Reload the plugin with `/combatlog reload`. |
| `eternalcombat.receiveupdates` | Receive notifications about new plugin versions on join. |
| `eternalcombat.bypass` | When exclude `excludeAdminsFromCombat` is set to `true` users with this permission will not be tagged |
## PlaceholderAPI
@@ -123,7 +132,7 @@ With Maven:
With Gradle:
```kts
compileOnly("com.eternalcode:eternalcombat-api:2.3.0-SNAPSHOT")
compileOnly("com.eternalcode:eternalcombat-api:2.4.0")
```
With Maven:
@@ -133,7 +142,7 @@ With Maven:
<dependency>
<groupId>com.eternalcode</groupId>
<artifactId>eternalcombat-api</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.4.0</version>
<scope>provided</scope>
</dependency>
```
Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 113 KiB

-1
View File
@@ -1,7 +1,6 @@
plugins {
java
eclipse
id("xyz.jpenilla.run-paper") version "2.2.3" apply false
}
tasks.jar {
+29 -1
View File
@@ -1,4 +1,32 @@
plugins { `kotlin-dsl` }
plugins {
`kotlin-dsl`
eclipse
}
repositories { gradlePluginPortal(); mavenCentral() }
kotlin { jvmToolchain(17) }
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.3.0")
implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.1")
implementation("net.minecrell:plugin-yml:0.6.0")
implementation("xyz.jpenilla:run-task:3.0.2")
}
sourceSets {
main {
java.setSrcDirs(emptyList<String>())
groovy.setSrcDirs(emptyList<String>())
resources.setSrcDirs(emptyList<String>())
}
test {
java.setSrcDirs(emptyList<String>())
kotlin.setSrcDirs(emptyList<String>())
groovy.setSrcDirs(emptyList<String>())
resources.setSrcDirs(emptyList<String>())
}
}
+17 -15
View File
@@ -2,34 +2,36 @@ object Versions {
const val SPIGOT_API = "1.17.1-R0.1-SNAPSHOT"
const val JUNIT_JUPITER_API = "5.13.4"
const val JUNIT_JUPITER_PARAMS = "5.13.4"
const val JUNIT_JUPITER_ENGINE = "5.13.4"
const val JUNIT_JUPITER_API = "6.0.2"
const val JUNIT_JUPITER_PARAMS = "6.0.2"
const val JUNIT_JUPITER_ENGINE = "6.0.2"
const val JETBRAINS_ANNOTATIONS = "26.0.2-1"
const val ETERNALCODE_COMMONS = "1.3.1"
const val MULTIFICATION = "1.2.2"
const val PACKETS_EVENTS = "2.9.5"
const val ETERNALCODE_COMMONS = "1.3.2"
const val MULTIFICATION = "1.2.4"
const val PACKETS_EVENTS = "2.11.1"
const val ADVENTURE_PLATFORM_BUKKIT = "4.4.1"
const val ADVENTURE_API = "4.24.0"
const val ADVENTURE_API = "4.26.1"
const val LITE_COMMANDS = "3.10.5"
const val OKAERI_CONFIGS_YAML_BUKKIT = "5.0.6"
const val LITE_COMMANDS = "3.10.9"
const val OKAERI_CONFIGS_SERDES_COMMONS = "5.0.13"
const val OKAERI_CONFIGS_SERDES_BUKKIT = "5.0.13"
const val GIT_CHECK = "1.0.0"
const val CAFFEINE = "3.2.3"
const val CAFFEINE = "3.2.2"
const val WORLD_GUARD_BUKKIT = "7.0.8"
const val B_STATS_BUKKIT = "3.1.0"
const val WORLD_GUARD_BUKKIT = "7.0.14"
const val PLACEHOLDER_API = "2.11.6"
const val PLACEHOLDER_API = "2.11.7"
const val LANDS_API = "7.23.1"
const val PAPERLIB = "1.0.8"
const val WORLDEDIT = "3ISh7ADm" //cannot use numeric version bc of duplicated version on modrinth
const val PACKETEVENTS = "2.11.1"
const val WORLDGUARD = "7.0.8"
const val LUCKPERMS = "5.5.17"
}
@@ -3,7 +3,7 @@ plugins {
}
group = "com.eternalcode"
version = "2.3.0-SNAPSHOT"
version = "2.4.1"
tasks.compileJava {
options.compilerArgs = listOf("-Xlint:deprecation", "-parameters")
@@ -4,7 +4,7 @@ plugins {
}
group = "com.eternalcode"
version = "2.3.0-SNAPSHOT"
version = "2.4.0"
java {
withSourcesJar()
@@ -3,11 +3,12 @@ plugins {
}
repositories {
maven("https://repo.eternalcode.pl/releases")
maven("https://repo.eternalcode.pl/snapshots")
mavenCentral()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.eternalcode.pl/releases")
maven("https://repo.eternalcode.pl/snapshots")
maven("https://storehouse.okaeri.eu/repository/maven-public/")
maven("https://repo.panda-lang.org/releases")
maven("https://maven.enginehub.org/repo/")
@@ -2,6 +2,9 @@ package com.eternalcode.combat.fight.event;
public enum CancelTagReason {
TAGOUT
TAGOUT,
PERMISSION_BYPASS,
ADMIN,
CREATIVE_MODE,
}
+153 -33
View File
@@ -1,10 +1,96 @@
import xyz.jpenilla.runpaper.task.RunServer
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
import io.papermc.hangarpublishplugin.model.Platforms
plugins {
java
id("com.gradleup.shadow") version "8.3.6"
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
`eternalcombat-java`
`eternalcombat-repositories`
id("net.minecrell.plugin-yml.bukkit")
id("com.gradleup.shadow")
id("xyz.jpenilla.run-paper")
id("com.modrinth.minotaur") version "2.8.10"
id("io.papermc.hangar-publish-plugin") version "0.1.4"
}
val buildNumber = providers.environmentVariable("GITHUB_RUN_NUMBER").orNull
val isRelease = providers.environmentVariable("GITHUB_EVENT_NAME").orNull == "release"
if (buildNumber != null && !isRelease) {
val offset = try {
val description = providers.exec {
commandLine("git", "describe", "--tags", "--long")
}.standardOutput.asText.get().trim()
val parts = description.split("-")
if (parts.size >= 3) parts[parts.size - 2] else "0"
} catch (e: Exception) {
try {
providers.exec {
commandLine("git", "rev-list", "--count", "HEAD")
}.standardOutput.asText.get().trim()
} catch (e: Exception) {
"0"
}
}
val baseVersion = project.version.toString().replace("-SNAPSHOT", "")
version = "$baseVersion-SNAPSHOT+$offset"
}
val changelogText = providers.environmentVariable("CHANGELOG").orElse(providers.exec {
commandLine("git", "log", "-1", "--format=%B")
}.standardOutput.asText)
logger.lifecycle("Building version: $version")
val paperVersions = (property("paperVersion") as String)
.split(",")
.map { it.trim() }
val hangarToken = providers.environmentVariable("HANGAR_API_TOKEN")
.orElse(providers.gradleProperty("hangarToken"))
val projectVersion = project.version.toString()
val releaseChannel = if (isRelease) "Release" else "Snapshot"
val shadowJarTask = tasks.shadowJar
modrinth {
token.set(providers.environmentVariable("MODRINTH_TOKEN"))
projectId.set("eternalcombat")
versionNumber.set(projectVersion)
versionType.set(if (isRelease) "release" else "beta")
uploadFile.set(shadowJarTask)
gameVersions.addAll(paperVersions)
loaders.addAll(listOf("paper", "spigot", "purpur"))
changelog.set(changelogText)
syncBodyFrom.set(rootProject.file("README.md").readText())
}
hangarPublish {
publications.register("plugin") {
version.set(projectVersion)
channel.set(releaseChannel)
changelog.set(changelogText)
id.set("eternalcombat")
apiKey.set(hangarToken)
platforms {
register(Platforms.PAPER) {
jar.set(shadowJarTask.flatMap { it.archiveFile })
platformVersions.set(paperVersions)
}
}
}
}
configurations.all {
resolutionStrategy {
eachDependency {
if (requested.group == "com.google.code.gson" && requested.name == "gson") {
useVersion("2.11.0")
because("WorldGuard requires strictly gson 2.11.0")
}
}
}
}
dependencies {
@@ -19,25 +105,45 @@ dependencies {
) { // Import WorldGuard but without its bundled WorldEdit.
exclude(group = "com.sk89q.worldedit")
}
// kyori
implementation("net.kyori:adventure-platform-bukkit:${Versions.ADVENTURE_PLATFORM_BUKKIT}")
implementation("net.kyori:adventure-text-minimessage:${Versions.ADVENTURE_API}")
implementation("net.kyori:adventure-api") {
version {
strictly(Versions.ADVENTURE_API)
}
}
compileOnly("com.github.angeschossen:LandsAPI:7.15.20")
// EternalCode Commons (split modules)
implementation("com.eternalcode:eternalcode-commons-shared:+")
implementation("com.eternalcode:eternalcode-commons-bukkit:+")
implementation("com.eternalcode:eternalcode-commons-adventure:+")
// litecommands
implementation("dev.rollczi:litecommands-bukkit:${Versions.LITE_COMMANDS}")
// Other libs
implementation("net.kyori:adventure-api:4.17.0")
implementation("net.kyori:adventure-text-minimessage:4.17.0")
implementation("net.kyori:adventure-platform-bukkit:4.3.3")
implementation("dev.rollczi:litecommands-bukkit:3.10.5")
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
implementation("org.bstats:bstats-bukkit:3.0.2")
implementation("io.papermc:paperlib:1.0.8")
// Okaeri configs
implementation("eu.okaeri:okaeri-configs-serdes-commons:${Versions.OKAERI_CONFIGS_SERDES_COMMONS}")
implementation("eu.okaeri:okaeri-configs-serdes-bukkit:${Versions.OKAERI_CONFIGS_SERDES_BUKKIT}")
implementation("com.eternalcode:multification-bukkit:1.2.2")
implementation("com.eternalcode:multification-okaeri:1.1.4")
implementation("com.eternalcode:gitcheck:1.0.0")
// caffeine
implementation("com.github.ben-manes.caffeine:caffeine:${Versions.CAFFEINE}")
implementation("com.eternalcode:eternalcode-commons-adventure:${Versions.ETERNALCODE_COMMONS}")
implementation("com.eternalcode:eternalcode-commons-bukkit:${Versions.ETERNALCODE_COMMONS}")
implementation("com.eternalcode:eternalcode-commons-shared:${Versions.ETERNALCODE_COMMONS}")
implementation("com.eternalcode:eternalcode-commons-updater:${Versions.ETERNALCODE_COMMONS}")
// worldguard
compileOnly("com.sk89q.worldguard:worldguard-bukkit:${Versions.WORLD_GUARD_BUKKIT}")
// PlaceholderAPI
compileOnly("me.clip:placeholderapi:${Versions.PLACEHOLDER_API}")
// Lands
compileOnly("com.github.angeschossen:LandsAPI:${Versions.LANDS_API}")
// Multification
implementation("com.eternalcode:multification-bukkit:${Versions.MULTIFICATION}")
implementation("com.eternalcode:multification-okaeri:${Versions.MULTIFICATION}")
compileOnly("com.github.retrooper:packetevents-spigot:${Versions.PACKETS_EVENTS}")
implementation("io.papermc:paperlib:${Versions.PAPERLIB}")
implementation("eu.okaeri:okaeri-configs-core:5.0.9")
implementation("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.9")
@@ -46,8 +152,6 @@ dependencies {
implementation("eu.okaeri:okaeri-configs-serdes-bukkit:5.0.9")
}
java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }
bukkit {
name = "EternalCombat"
main = "com.eternalcode.combat.CombatPlugin"
@@ -55,12 +159,33 @@ bukkit {
apiVersion = "1.19"
authors = listOf("EternalCodeTeam")
prefix = "EternalCombat"
softDepend = listOf("Lands")
depend = listOf("PacketEvents-OG")
name = "EternalCombat"
load = BukkitPluginDescription.PluginLoadOrder.POSTWORLD
softDepend = listOf(
"Lands",
"WorldGuard"
)
depend = listOf(
"packetevents",
)
version = "${project.version}"
foliaSupported = false
}
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
tasks {
runServer {
minecraftVersion("1.19.4")
downloadPlugins.modrinth("WorldEdit", Versions.WORLDEDIT)
downloadPlugins.modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot")
downloadPlugins.modrinth("WorldGuard", Versions.WORLDGUARD)
downloadPlugins.modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit")
}
}
tasks.shadowJar {
archiveFileName.set("EternalCombat v${project.version}.jar")
exclude(
"org/intellij/lang/annotations/**",
"org/jetbrains/annotations/**",
@@ -70,6 +195,7 @@ tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJ
"org/checkerframework/**",
"com/google/errorprone/**"
)
val prefix = "com.eternalcode.combat.libs"
listOf(
"eu.okaeri",
@@ -82,14 +208,8 @@ tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJ
"com.github.benmanes.caffeine",
"com.eternalcode.commons",
"com.eternalcode.multification",
"io.papermc"
).forEach { relocate(it, "$prefix.$it") }
}
tasks.named<RunServer>("runServer") {
minecraftVersion("1.19.4")
downloadPlugins {
url("https://github.com/retrooper/packetevents/releases/download/v2.8.0/packetevents-spigot-2.8.0.jar")
"io.papermc.lib"
).forEach { pack ->
relocate(pack, "$prefix.$pack")
}
}
@@ -8,6 +8,9 @@ import com.eternalcode.combat.border.animation.particle.ParticleController;
import com.eternalcode.combat.bridge.BridgeService;
import com.eternalcode.combat.crystalpvp.RespawnAnchorListener;
import com.eternalcode.combat.crystalpvp.EndCrystalListener;
import com.eternalcode.combat.fight.controller.FightBypassAdminController;
import com.eternalcode.combat.fight.controller.FightBypassCreativeController;
import com.eternalcode.combat.fight.controller.FightBypassPermissionController;
import com.eternalcode.combat.fight.drop.DropKeepInventoryService;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.drop.DropService;
@@ -49,17 +52,16 @@ import com.eternalcode.combat.updater.UpdaterNotificationController;
import com.eternalcode.combat.updater.UpdaterService;
import com.eternalcode.commons.adventure.AdventureLegacyColorPostProcessor;
import com.eternalcode.commons.adventure.AdventureLegacyColorPreProcessor;
import com.eternalcode.commons.bukkit.scheduler.BukkitSchedulerImpl;
import com.eternalcode.commons.scheduler.Scheduler;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.multification.notice.Notice;
import com.google.common.base.Stopwatch;
import dev.rollczi.litecommands.LiteCommands;
import dev.rollczi.litecommands.bukkit.LiteBukkitFactory;
import dev.rollczi.litecommands.bukkit.LiteBukkitMessages;
import java.time.Duration;
import net.kyori.adventure.platform.AudienceProvider;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bstats.bukkit.Metrics;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.event.entity.PlayerDeathEvent;
@@ -73,7 +75,6 @@ import java.util.stream.Stream;
public final class CombatPlugin extends JavaPlugin implements EternalCombatApi {
private static final String FALLBACK_PREFIX = "eternalcombat";
private static final int BSTATS_METRICS_ID = 17803;
private FightManager fightManager;
private FightPearlService fightPearlService;
@@ -99,10 +100,10 @@ public final class CombatPlugin extends JavaPlugin implements EternalCombatApi {
ConfigService configService = new ConfigService();
EventManager eventManager = new EventManager(this);
Scheduler scheduler = new BukkitSchedulerImpl(this);
PluginConfig pluginConfig = configService.create(PluginConfig.class, new File(dataFolder, "config.yml"));
MinecraftScheduler scheduler = CombatSchedulerAdapter.getAdaptiveScheduler(this);
this.fightManager = new FightManagerImpl(eventManager);
this.fightPearlService = new FightPearlServiceImpl(pluginConfig.pearl);
this.fightTagOutService = new FightTagOutServiceImpl();
@@ -157,9 +158,7 @@ public final class CombatPlugin extends JavaPlugin implements EternalCombatApi {
.build();
FightTask fightTask = new FightTask(server, pluginConfig, this.fightManager, noticeService);
this.getServer().getScheduler().runTaskTimer(this, fightTask, 20L, 20L);
new Metrics(this, BSTATS_METRICS_ID);
scheduler.timer(fightTask, Duration.ofSeconds(1), Duration.ofSeconds(1));
Stream.of(
new PercentDropModifier(pluginConfig.drop),
@@ -169,14 +168,17 @@ public final class CombatPlugin extends JavaPlugin implements EternalCombatApi {
eventManager.subscribe(
new FightTagController(this.fightManager, pluginConfig),
new FightUnTagController(this.fightManager, pluginConfig, logoutService),
new FightBypassAdminController(server, pluginConfig),
new FightBypassPermissionController(server, pluginConfig),
new FightBypassCreativeController(server, pluginConfig),
new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server),
new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService),
new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage),
new KnockbackRegionController(noticeService, this.regionProvider, this.fightManager, knockbackService, server),
new FightEffectController(pluginConfig.effect, this.fightEffectService, this.fightManager, this.getServer()),
new FightEffectController(pluginConfig.effect, this.fightEffectService, this.fightManager, server),
new FightTagOutController(this.fightTagOutService),
new FightMessageController(this.fightManager, noticeService, pluginConfig, this.getServer()),
new BorderTriggerController(borderService, () -> pluginConfig.border, fightManager, server),
new FightMessageController(this.fightManager, noticeService, pluginConfig, server),
new BorderTriggerController(borderService, () -> pluginConfig.border, fightManager, server, scheduler),
new ParticleController(borderService, () -> pluginConfig.border.particle, scheduler, server),
new BorderBlockController(borderService, () -> pluginConfig.border.block, scheduler, server),
new EndCrystalListener(this, this.fightManager, pluginConfig),
@@ -0,0 +1,20 @@
package com.eternalcode.combat;
import com.eternalcode.commons.bukkit.scheduler.BukkitSchedulerImpl;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import java.util.logging.Logger;
import org.bukkit.plugin.Plugin;
public final class CombatSchedulerAdapter {
private CombatSchedulerAdapter() {
throw new UnsupportedOperationException("This is an utility class and cannot be instantiated");
}
public static MinecraftScheduler getAdaptiveScheduler(Plugin plugin) {
Logger logger = plugin.getLogger();
logger.info("» Detected Bukkit/Paper environment. Using BukkitScheduler.");
return new BukkitSchedulerImpl(plugin);
}
}
@@ -14,7 +14,6 @@ import java.time.Duration;
import org.bukkit.command.CommandSender;
@Command(name = "combatlog", aliases = "combat")
@Permission("eternalcombat.reload")
public class EternalCombatReloadCommand {
private static final Notice RELOAD_MESSAGE = BukkitNotice.builder()
@@ -31,6 +30,7 @@ public class EternalCombatReloadCommand {
@Async
@Execute(name = "reload")
@Permission("eternalcombat.reload")
void execute(@Context CommandSender sender) {
Stopwatch stopwatch = Stopwatch.createStarted();
this.configService.reload();
@@ -2,18 +2,24 @@ package com.eternalcode.combat.border;
import org.jetbrains.annotations.Nullable;
public record BorderPoint(int x, int y, int z, @Nullable BorderPoint inclusive) {
public record BorderPoint(int x, int y, int z, @Nullable BorderPoint innerPoint) {
public BorderPoint(int x, int y, int z) {
this(x, y, z, null);
}
public BorderPoint toInclusive() {
if (inclusive == null) {
/**
* This point represents an adjusted coordinate that takes into account the block's volume (thickness)
* and is used for logical placement and grouping, especially for assigning border blocks to the
* correct chunk when they are on the very edge of a chunk boundary.
* This ensures the block is considered to be on the "inner" side of the border for chunk-based logic.
*/
@Override
public BorderPoint innerPoint() {
if (this.innerPoint == null) {
return this;
}
return inclusive;
return this.innerPoint;
}
}
@@ -4,6 +4,7 @@ import com.eternalcode.combat.border.event.BorderHideAsyncEvent;
import com.eternalcode.combat.border.event.BorderShowAsyncEvent;
import com.eternalcode.combat.event.EventManager;
import com.eternalcode.combat.region.RegionProvider;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.commons.scheduler.Scheduler;
import dev.rollczi.litecommands.shared.Lazy;
import java.util.ArrayList;
@@ -19,7 +20,7 @@ import org.bukkit.entity.Player;
public class BorderServiceImpl implements BorderService {
private final Scheduler scheduler;
private final MinecraftScheduler scheduler;
private final EventManager eventManager;
private final Supplier<BorderSettings> settings;
@@ -27,7 +28,7 @@ public class BorderServiceImpl implements BorderService {
private final BorderTriggerIndex borderIndexes;
private final BorderActivePointsIndex activeBorderIndex = new BorderActivePointsIndex();
public BorderServiceImpl(Scheduler scheduler, Server server, RegionProvider provider, EventManager eventManager, Supplier<BorderSettings> settings) {
public BorderServiceImpl(MinecraftScheduler scheduler, Server server, RegionProvider provider, EventManager eventManager, Supplier<BorderSettings> settings) {
this.scheduler = scheduler;
this.eventManager = eventManager;
this.settings = settings;
@@ -128,8 +129,8 @@ public class BorderServiceImpl implements BorderService {
if (borderMax.y() <= realMaxY) { // Top wall
for (int currentX = realMinX; currentX <= realMaxX; currentX++) {
for (int currentZ = realMinZ; currentZ <= realMaxZ; currentZ++) {
BorderPoint inclusive = new BorderPoint(Math.max(realMinX, currentX - 1), realMaxY - 1, Math.max(realMinZ, currentZ - 1));
addPoint(points, currentX, realMaxY, currentZ, playerLocation, inclusive);
BorderPoint innerPoint = new BorderPoint(Math.max(realMinX, currentX - 1), realMaxY - 1, Math.max(realMinZ, currentZ - 1));
addPoint(points, currentX, realMaxY, currentZ, playerLocation, innerPoint);
}
}
}
@@ -145,8 +146,8 @@ public class BorderServiceImpl implements BorderService {
if (borderMax.x() <= realMaxX) { // East wall (right)
for (int currentY = realMinY; currentY <= realMaxY; currentY++) {
for (int currentZ = realMinZ; currentZ <= realMaxZ; currentZ++) {
BorderPoint inclusive = new BorderPoint(realMaxX - 1, Math.max(realMinY, currentY - 1), Math.max(realMinZ, currentZ - 1));
addPoint(points, realMaxX, currentY, currentZ, playerLocation, inclusive);
BorderPoint innerPoint = new BorderPoint(realMaxX - 1, Math.max(realMinY, currentY - 1), Math.max(realMinZ, currentZ - 1));
addPoint(points, realMaxX, currentY, currentZ, playerLocation, innerPoint);
}
}
}
@@ -162,8 +163,8 @@ public class BorderServiceImpl implements BorderService {
if (borderMax.z() <= realMaxZ) { // South wall (back)
for (int currentX = realMinX; currentX <= realMaxX; currentX++) {
for (int currentY = realMinY; currentY <= realMaxY; currentY++) {
BorderPoint inclusive = new BorderPoint(Math.max(realMinX, currentX - 1), Math.max(realMinY, currentY - 1), realMaxZ - 1);
addPoint(points, currentX, currentY, realMaxZ, playerLocation, inclusive);
BorderPoint innerPoint = new BorderPoint(Math.max(realMinX, currentX - 1), Math.max(realMinY, currentY - 1), realMaxZ - 1);
addPoint(points, currentX, currentY, realMaxZ, playerLocation, innerPoint);
}
}
}
@@ -171,9 +172,9 @@ public class BorderServiceImpl implements BorderService {
return points;
}
private void addPoint(List<BorderPoint> points, int x, int y, int z, Location playerLocation, BorderPoint inclusive) {
private void addPoint(List<BorderPoint> points, int x, int y, int z, Location playerLocation, BorderPoint innerPoint) {
if (isVisible(x, y, z, playerLocation)) {
points.add(new BorderPoint(x, y, z, inclusive));
points.add(new BorderPoint(x, y, z, innerPoint));
}
}
@@ -3,6 +3,8 @@ package com.eternalcode.combat.border;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.event.FightTagEvent;
import com.eternalcode.combat.fight.event.FightUntagEvent;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import java.time.Duration;
import java.util.function.Supplier;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -15,16 +17,26 @@ import org.bukkit.event.player.PlayerTeleportEvent;
public class BorderTriggerController implements Listener {
private static final long BORDER_WORK_AROUND_DELAY_MILLIS = 250;
private final BorderService borderService;
private final Supplier<BorderSettings> border;
private final FightManager fightManager;
private final Server server;
private final MinecraftScheduler scheduler;
public BorderTriggerController(BorderService borderService, Supplier<BorderSettings> border, FightManager fightManager, Server server) {
public BorderTriggerController(
BorderService borderService,
Supplier<BorderSettings> border,
FightManager fightManager,
Server server,
MinecraftScheduler scheduler
) {
this.borderService = borderService;
this.border = border;
this.fightManager = fightManager;
this.server = server;
this.scheduler = scheduler;
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
@@ -86,7 +98,11 @@ public class BorderTriggerController implements Listener {
return;
}
borderService.clearBorder(player);
// Due to race condition in PlayerMoveEvent and FightUntagEvent - border can be triggered after death and untag of player - solution delayed removal of border
this.scheduler.runLater(() -> {
if (!this.fightManager.isInCombat(player.getUniqueId())) {
this.borderService.clearBorder(player);
}
}, Duration.ofMillis(BORDER_WORK_AROUND_DELAY_MILLIS));
}
}
@@ -2,6 +2,7 @@ package com.eternalcode.combat.border;
import com.eternalcode.combat.region.Region;
import com.eternalcode.combat.region.RegionProvider;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.commons.scheduler.Scheduler;
import java.time.Duration;
import java.util.ArrayList;
@@ -17,13 +18,13 @@ import org.bukkit.World;
class BorderTriggerIndex {
private final Server server;
private final Scheduler scheduler;
private final MinecraftScheduler scheduler;
private final RegionProvider provider;
private final Supplier<BorderSettings> settings;
private final Map<String, BorderTriggerIndexBucket> borderIndexes = new HashMap<>();
private BorderTriggerIndex(Server server, Scheduler scheduler, RegionProvider provider, Supplier<BorderSettings> settings) {
private BorderTriggerIndex(Server server, MinecraftScheduler scheduler, RegionProvider provider, Supplier<BorderSettings> settings) {
this.server = server;
this.scheduler = scheduler;
this.provider = provider;
@@ -56,7 +57,7 @@ class BorderTriggerIndex {
});
}
static BorderTriggerIndex started(Server server, Scheduler scheduler, RegionProvider provider, Supplier<BorderSettings> settings) {
static BorderTriggerIndex started(Server server, MinecraftScheduler scheduler, RegionProvider provider, Supplier<BorderSettings> settings) {
BorderTriggerIndex index = new BorderTriggerIndex(server, scheduler, provider, settings);
scheduler.timerAsync(() -> index.updateWorlds(), Duration.ZERO, settings.get().indexRefreshDelay());
return index;
@@ -15,6 +15,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange.EncodedBlock;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
@@ -25,11 +26,12 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
public class BorderBlockController implements Listener {
@@ -37,7 +39,7 @@ public class BorderBlockController implements Listener {
public static final PlayerManager PLAYER_MANAGER = PACKET_EVENTS.getPlayerManager();
public static final ClientVersion SERVER_VERSION = PACKET_EVENTS.getServerManager().getVersion().toClientVersion();
public static final int AIR_ID = WrappedBlockState.getDefaultState(SERVER_VERSION, StateTypes.AIR).getGlobalId();
public static final WrappedBlockState AIR_ID = WrappedBlockState.getDefaultState(SERVER_VERSION, StateTypes.AIR);
public static final int MINECRAFT_CHUNK_SHIFT = 4;
private final BorderService borderService;
@@ -46,6 +48,7 @@ public class BorderBlockController implements Listener {
private final Set<UUID> playersToUpdate = ConcurrentHashMap.newKeySet();
private final Map<UUID, Object> lockedPlayers = new ConcurrentHashMap<>();
private final Map<UUID, Map<BorderPoint, WrappedBlockState>> originalBlocks = new ConcurrentHashMap<>();
private final ChunkCache chunkCache;
public BorderBlockController(BorderService borderService, Supplier<BlockSettings> settings, Scheduler scheduler, Server server) {
@@ -59,37 +62,52 @@ public class BorderBlockController implements Listener {
@EventHandler
void onBorderShowAsyncEvent(BorderShowAsyncEvent event) {
if (!settings.get().enabled) {
if (!this.settings.get().enabled) {
return;
}
Player player = event.getPlayer();
Set<BorderPoint> borderPoints = this.getPointsWithoutAir(player, event.getPoints());
UUID playerId = player.getUniqueId();
event.setPoints(borderPoints);
this.showBlocks(player, borderPoints);
this.playersToUpdate.add(player.getUniqueId());
synchronized (this.getLock(playerId)) {
Set<BorderPoint> borderPoints = this.savePassablePoints(player, event.getPoints());
event.setPoints(borderPoints);
this.showBorder(player, borderPoints);
this.playersToUpdate.add(playerId);
}
}
@EventHandler
void onBorderHideAsyncEvent(BorderHideAsyncEvent event) {
if (!settings.get().enabled) {
if (!this.settings.get().enabled) {
return;
}
Object lock = lockedPlayers.computeIfAbsent(event.getPlayer().getUniqueId(), k -> new Object());
synchronized (lock) {
this.hideBlocks(event.getPlayer(), event.getPoints());
UUID playerId = event.getPlayer().getUniqueId();
synchronized (this.getLock(playerId)) {
this.hideBorder(event.getPlayer(), event.getPoints());
Set<BorderPoint> border = this.borderService.getActiveBorder(event.getPlayer());
if (border.isEmpty()) {
this.playersToUpdate.remove(event.getPlayer().getUniqueId());
this.playersToUpdate.remove(playerId);
this.originalBlocks.remove(playerId);
}
}
}
@EventHandler
void onPlayerQuit(PlayerQuitEvent event) {
UUID playerId = event.getPlayer().getUniqueId();
this.playersToUpdate.remove(playerId);
this.originalBlocks.remove(playerId);
this.lockedPlayers.remove(playerId);
}
private void updatePlayers() {
if (!settings.get().enabled) {
if (!this.settings.get().enabled) {
return;
}
@@ -105,93 +123,109 @@ public class BorderBlockController implements Listener {
}
private void updatePlayer(UUID uuid, Player player) {
Object lock = lockedPlayers.computeIfAbsent(uuid, k -> new Object());
synchronized (lock) {
synchronized (this.getLock(uuid)) {
Set<BorderPoint> border = this.borderService.getActiveBorder(player);
if (border.isEmpty()) {
this.playersToUpdate.remove(uuid);
this.originalBlocks.remove(uuid);
return;
}
this.showBlocks(player, border);
Set<BorderPoint> passablePoints = this.savePassablePoints(player, border);
this.showBorder(player, passablePoints);
}
}
private void showBlocks(Player player, Collection<BorderPoint> blocks) {
this.splitByChunks(blocks).entrySet().stream()
.map(chunkBlocks -> toMultiBlockChangePacket(chunkBlocks))
.forEach(change -> PLAYER_MANAGER.sendPacket(player, change));
private void showBorder(Player player, Collection<BorderPoint> blocks) {
this.groupByChunkPacket(blocks).forEach((chunkPos, chunkPoints) -> {
EncodedBlock[] encodedBlocks = chunkPoints.stream()
.map(point -> toBorderBlock(point))
.toArray(EncodedBlock[]::new);
PLAYER_MANAGER.sendPacket(player, new WrapperPlayServerMultiBlockChange(chunkPos, true, encodedBlocks));
});
}
private WrapperPlayServerMultiBlockChange toMultiBlockChangePacket(Entry<Vector3i, Set<BorderPoint>> chunkBlocks) {
EncodedBlock[] encodedBlocks = chunkBlocks.getValue().stream()
.map(borderPoint -> this.toEncodedBlock(borderPoint))
.toArray(value -> new EncodedBlock[value]);
private void hideBorder(Player player, Collection<BorderPoint> blocks) {
UUID playerId = player.getUniqueId();
Map<BorderPoint, WrappedBlockState> savedBlocks = this.originalBlocks.get(playerId);
return new WrapperPlayServerMultiBlockChange(chunkBlocks.getKey(), true, encodedBlocks);
this.groupByChunkPacket(blocks).forEach((chunkPosition, chunkPoints) -> {
EncodedBlock[] originalBlocks = chunkPoints.stream()
.map(point -> this.toOriginalBlock(point, savedBlocks))
.toArray(EncodedBlock[]::new);
PLAYER_MANAGER.sendPacket(player, new WrapperPlayServerMultiBlockChange(chunkPosition, true, originalBlocks));
});
if (savedBlocks != null) {
blocks.forEach(key -> savedBlocks.remove(key));
}
}
private void hideBlocks(Player player, Collection<BorderPoint> blocks) {
this.splitByChunks(blocks).entrySet().stream()
.map(chunkBlocks -> toMultiAirChangePacket(chunkBlocks))
.forEach(change -> PLAYER_MANAGER.sendPacket(player, change));
}
private Set<BorderPoint> savePassablePoints(Player player, Collection<BorderPoint> points) {
UUID playerId = player.getUniqueId();
Map<BorderPoint, WrappedBlockState> savedBlocks = this.originalBlocks.computeIfAbsent(playerId, key -> new ConcurrentHashMap<>());
private WrapperPlayServerMultiBlockChange toMultiAirChangePacket(Entry<Vector3i, Set<BorderPoint>> chunkBlocks) {
EncodedBlock[] encodedBlocks = chunkBlocks.getValue().stream()
.map(point -> new EncodedBlock(AIR_ID, point.x(), point.y(), point.z()))
.toArray(value -> new EncodedBlock[value]);
return new WrapperPlayServerMultiBlockChange(chunkBlocks.getKey(), true, encodedBlocks);
}
private Set<BorderPoint> getPointsWithoutAir(Player player, Collection<BorderPoint> blocks) {
Map<ChunkLocation, Set<BorderPoint>> chunksToProcess = blocks.stream()
.map(borderPoint -> borderPoint.toInclusive())
.collect(Collectors.groupingBy(
inclusive -> new ChunkLocation(inclusive.x() >> MINECRAFT_CHUNK_SHIFT, inclusive.z() >> MINECRAFT_CHUNK_SHIFT),
Collectors.toSet()
));
return chunksToProcess.entrySet().stream()
.flatMap(entry -> getPointsWithoutAirOnChunk(player, entry))
return this.groupByChunk(points).entrySet().stream()
.flatMap(entry -> this.savePassableBlock(player, entry, savedBlocks))
.collect(Collectors.toSet());
}
private Stream<BorderPoint> getPointsWithoutAirOnChunk(Player player, Entry<ChunkLocation, Set<BorderPoint>> entry) {
ChunkSnapshot snapshot = this.chunkCache.loadSnapshot(player, entry.getKey());
private Stream<BorderPoint> savePassableBlock(Player player, Entry<ChunkLocation, Set<BorderPoint>> entry, Map<BorderPoint, WrappedBlockState> savedBlocks) {
ChunkSnapshot snapshot = this.chunkCache.loadSnapshot(player, entry.getKey());
if (snapshot == null) {
return Stream.empty();
}
return entry.getValue().stream()
.filter(point -> isAir(entry.getKey(), point, snapshot));
ChunkLocation chunk = entry.getKey();
return entry.getValue().stream().filter(point -> this.saveBlockIfPassable(point, chunk, snapshot, savedBlocks));
}
private static boolean isAir(ChunkLocation location, BorderPoint point, ChunkSnapshot chunk) {
int xInsideChunk = point.x() - (location.x() << MINECRAFT_CHUNK_SHIFT);
int zInsideChunk = point.z() - (location.z() << MINECRAFT_CHUNK_SHIFT);
Material material = chunk.getBlockType(xInsideChunk, point.y(), zInsideChunk);
private boolean saveBlockIfPassable(BorderPoint point, ChunkLocation chunk, ChunkSnapshot snapshot, Map<BorderPoint, WrappedBlockState> savedBlocks) {
int localX = point.x() - (chunk.x() << MINECRAFT_CHUNK_SHIFT);
int localZ = point.z() - (chunk.z() << MINECRAFT_CHUNK_SHIFT);
return material.isAir();
BlockData blockData = snapshot.getBlockData(localX, point.y(), localZ);
if (blockData.getMaterial().isSolid()) {
return false;
}
savedBlocks.put(point, SpigotConversionUtil.fromBukkitBlockData(blockData));
return true;
}
private Map<Vector3i, Set<BorderPoint>> splitByChunks(Collection<BorderPoint> blocks) {
return blocks.stream().collect(Collectors.groupingBy(
block -> new Vector3i(
block.x() >> MINECRAFT_CHUNK_SHIFT,
block.y() >> MINECRAFT_CHUNK_SHIFT,
block.z() >> MINECRAFT_CHUNK_SHIFT
),
private EncodedBlock toBorderBlock(BorderPoint point) {
StateType type = this.settings.get().type.getStateType(point);
int blockId = WrappedBlockState.getDefaultState(SERVER_VERSION, type).getGlobalId();
return new EncodedBlock(blockId, point.x(), point.y(), point.z());
}
private EncodedBlock toOriginalBlock(BorderPoint point, Map<BorderPoint, WrappedBlockState> savedBlocks) {
WrappedBlockState blockId = savedBlocks != null ? savedBlocks.getOrDefault(point, AIR_ID) : AIR_ID;
return new EncodedBlock(blockId, point.x(), point.y(), point.z());
}
private Map<ChunkLocation, Set<BorderPoint>> groupByChunk(Collection<BorderPoint> points) {
return points.stream()
.map(borderPoint -> borderPoint.innerPoint())
.collect(Collectors.groupingBy(point -> new ChunkLocation(point.x() >> MINECRAFT_CHUNK_SHIFT, point.z() >> MINECRAFT_CHUNK_SHIFT),
Collectors.toSet()
));
}
private EncodedBlock toEncodedBlock(BorderPoint point) {
StateType type = settings.get().type.getStateType(point);
WrappedBlockState state = WrappedBlockState.getDefaultState(SERVER_VERSION, type);
return new EncodedBlock(state.getGlobalId(), point.x(), point.y(), point.z());
private Map<Vector3i, Set<BorderPoint>> groupByChunkPacket(Collection<BorderPoint> points) {
return points.stream().collect(Collectors.groupingBy(
point -> new Vector3i(point.x() >> MINECRAFT_CHUNK_SHIFT, point.y() >> MINECRAFT_CHUNK_SHIFT, point.z() >> MINECRAFT_CHUNK_SHIFT),
Collectors.toSet()
));
}
private Object getLock(UUID uuid) {
return this.lockedPlayers.computeIfAbsent(uuid, k -> new Object());
}
}
@@ -69,7 +69,7 @@ public class BridgeService {
initialize(
"PlaceholderAPI",
() -> new FightTagPlaceholder(this.fightManager, server, this.plugin).register(),
() -> new FightTagPlaceholder(this.config, this.fightManager, server, this.plugin).register(),
() -> this.logger.warning("PlaceholderAPI not found; skipping placeholders.")
);
}
@@ -1,5 +1,7 @@
package com.eternalcode.combat.bridge.placeholder;
import com.eternalcode.combat.config.implementation.PlaceholderSettings;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.FightTag;
import com.eternalcode.combat.util.DurationUtil;
@@ -14,23 +16,93 @@ import org.jetbrains.annotations.NotNull;
public class FightTagPlaceholder extends PlaceholderExpansion {
private static final String IDENTIFIER = "eternalcombat";
private final PlaceholderSettings placeholderSettings;
private final FightManager fightManager;
private final Server server;
private final Plugin plugin;
private static final String IDENTIFIER = "eternalcombat";
public FightTagPlaceholder(FightManager fightManager, Server server, Plugin plugin) {
public FightTagPlaceholder(PluginConfig pluginConfig, FightManager fightManager, Server server, Plugin plugin) {
this.placeholderSettings = pluginConfig.placeholders;
this.fightManager = fightManager;
this.server = server;
this.plugin = plugin;
}
@Override
public String onRequest(OfflinePlayer player, String identifier) {
return switch (identifier) {
case "remaining_millis" -> this.handleRemainingMillis(player);
case "remaining_seconds" -> this.handleRemainingSeconds(player);
case "opponent" -> this.handleOpponent(player);
case "opponent_health" -> this.handleOpponentHealth(player);
case "isInCombat" -> this.handleIsInCombat(player);
case "isInCombat_formatted" -> this.handleIsInCombatFormatted(player);
default -> null;
};
}
private String handleRemainingMillis(OfflinePlayer player) {
return this.getFightTag(player)
.map(tag -> DurationParser.TIME_UNITS.format(tag.getRemainingDuration()))
.orElse("");
}
private String handleRemainingSeconds(OfflinePlayer player) {
return this.getFightTag(player)
.map(tag -> DurationUtil.format(tag.getRemainingDuration()))
.orElse("");
}
private String handleOpponent(OfflinePlayer player) {
return this.getTagger(player)
.map(Player::getName)
.orElse("");
}
private String handleOpponentHealth(OfflinePlayer player) {
return this.getTagger(player)
.map(tagger -> String.format("%.2f", tagger.getHealth()))
.orElse("");
}
private String handleIsInCombat(OfflinePlayer player) {
return String.valueOf(this.isPlayerInCombat(player));
}
private String handleIsInCombatFormatted(OfflinePlayer player) {
return this.isPlayerInCombat(player)
? this.placeholderSettings.isInCombatFormattedTrue
: this.placeholderSettings.isInCombatFormattedFalse;
}
private boolean isPlayerInCombat(OfflinePlayer player) {
Player onlinePlayer = player.getPlayer();
return onlinePlayer != null && this.fightManager.isInCombat(onlinePlayer.getUniqueId());
}
private @NotNull Optional<Player> getTagger(OfflinePlayer player) {
return this.getFightTag(player)
.map(FightTag::getTagger)
.map(this.server::getPlayer);
}
private Optional<FightTag> getFightTag(OfflinePlayer player) {
Player onlinePlayer = player.getPlayer();
if (onlinePlayer == null || !this.fightManager.isInCombat(onlinePlayer.getUniqueId())) {
return Optional.empty();
}
return Optional.of(this.fightManager.getTag(onlinePlayer.getUniqueId()));
}
@Override
public boolean canRegister() {
return true;
}
@Override
public @NotNull String getIdentifier() {
return IDENTIFIER;
@@ -45,54 +117,4 @@ public class FightTagPlaceholder extends PlaceholderExpansion {
public @NotNull String getVersion() {
return this.plugin.getDescription().getVersion();
}
@Override
public String onRequest(OfflinePlayer player, String identifier) {
if (identifier.equals("remaining_seconds")) {
return this.getFightTag(player)
.map(fightTagInter -> DurationUtil.format(fightTagInter.getRemainingDuration()))
.orElse("");
}
if (identifier.equals("remaining_millis")) {
return this.getFightTag(player)
.map(fightTag -> DurationParser.TIME_UNITS.format(fightTag.getRemainingDuration()))
.orElse("");
}
if (identifier.equals("opponent")) {
return this.getTagger(player)
.map(tagger -> tagger.getName())
.orElse("");
}
if (identifier.equals("opponent_health")) {
return this.getTagger(player)
.map(tagger -> String.format("%.2f", tagger.getHealth()))
.orElse("");
}
return null;
}
private @NotNull Optional<Player> getTagger(OfflinePlayer player) {
return this.getFightTag(player)
.map(fightTagInter -> fightTagInter.getTagger())
.map(taggerId -> this.server.getPlayer(taggerId));
}
private Optional<FightTag> getFightTag(OfflinePlayer player) {
Player onlinePlayer = player.getPlayer();
if (onlinePlayer != null) {
if (!this.fightManager.isInCombat(onlinePlayer.getUniqueId())) {
return Optional.empty();
}
return Optional.of(this.fightManager.getTag(onlinePlayer.getUniqueId()));
}
return Optional.empty();
}
}
@@ -0,0 +1,14 @@
package com.eternalcode.combat.config.implementation;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
public class PlaceholderSettings extends OkaeriConfig {
@Comment("Text returned by %eternalcombat_isInCombat_formatted% placeholder when the player is in combat")
public String isInCombatFormattedTrue = "In Combat";
@Comment("Text returned by %eternalcombat_isInCombat_formatted% placeholder when the player is out of combat")
public String isInCombatFormattedFalse = "Not In Combat";
}
@@ -105,6 +105,13 @@ public class PluginConfig extends OkaeriConfig {
})
public CombatSettings combat = new CombatSettings();
@Comment({
" ",
"# Settings related to placeholders used in the plugin.",
"# Configure default values returned by placeholders"
})
public PlaceholderSettings placeholders = new PlaceholderSettings();
@Comment({
" ",
"# Customize the messages displayed by the plugin.",
@@ -0,0 +1,37 @@
package com.eternalcode.combat.fight.controller;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.event.CancelTagReason;
import com.eternalcode.combat.fight.event.FightTagEvent;
import java.util.UUID;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class FightBypassAdminController implements Listener {
private final Server server;
private final PluginConfig config;
public FightBypassAdminController(Server server, PluginConfig config) {
this.server = server;
this.config = config;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
void onFightTagEvent(FightTagEvent event) {
UUID uniqueId = event.getPlayer();
Player player = this.server.getPlayer(uniqueId);
if (player == null) {
return;
}
if (this.config.admin.excludeAdminsFromCombat && player.isOp()) {
event.setCancelReason(CancelTagReason.ADMIN);
event.setCancelled(true);
}
}
}
@@ -0,0 +1,39 @@
package com.eternalcode.combat.fight.controller;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.event.CancelTagReason;
import com.eternalcode.combat.fight.event.FightTagEvent;
import java.util.UUID;
import org.bukkit.GameMode;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class FightBypassCreativeController implements Listener {
private final Server server;
private final PluginConfig config;
public FightBypassCreativeController(Server server, PluginConfig config) {
this.server = server;
this.config = config;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
void onFightTagEvent(FightTagEvent event) {
UUID uniqueId = event.getPlayer();
Player player = this.server.getPlayer(uniqueId);
if (player == null) {
return;
}
if (this.config.admin.excludeCreativePlayersFromCombat && player.getGameMode() == GameMode.CREATIVE) {
event.setCancelReason(CancelTagReason.CREATIVE_MODE);
event.setCancelled(true);
}
}
}
@@ -0,0 +1,39 @@
package com.eternalcode.combat.fight.controller;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.event.CancelTagReason;
import com.eternalcode.combat.fight.event.FightTagEvent;
import java.util.UUID;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class FightBypassPermissionController implements Listener {
private static final String BYPASS_PERMISSION = "eternalcombat.bypass";
private final Server server;
private final PluginConfig config;
public FightBypassPermissionController(Server server, PluginConfig config) {
this.server = server;
this.config = config;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
void onFightTagEvent(FightTagEvent event) {
UUID uniqueId = event.getPlayer();
Player player = this.server.getPlayer(uniqueId);
if (player == null) {
return;
}
if (player.hasPermission(BYPASS_PERMISSION) && this.config.admin.excludeAdminsFromCombat) {
event.setCancelReason(CancelTagReason.PERMISSION_BYPASS);
event.setCancelled(true);
}
}
}
@@ -4,7 +4,6 @@ import com.eternalcode.combat.WhitelistBlacklistMode;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.event.CauseOfTag;
import org.bukkit.GameMode;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
@@ -56,14 +55,6 @@ public class FightTagController implements Listener {
return;
}
if (this.cannotBeTagged(attacker)) {
return;
}
if (this.cannotBeTagged(attackedPlayerByPerson)) {
return;
}
if (this.config.combat.disableFlying) {
if (attackedPlayerByPerson.isFlying()) {
attackedPlayerByPerson.setFlying(false);
@@ -99,15 +90,6 @@ public class FightTagController implements Listener {
return;
}
if (this.cannotBeTagged(player)) {
return;
}
boolean hasBypass = player.hasPermission("eternalcombat.bypass");
if (hasBypass) {
return;
}
Duration combatTime = this.config.settings.combatTimerDuration;
UUID uuid = player.getUniqueId();
@@ -145,18 +127,6 @@ public class FightTagController implements Listener {
return this.config.settings.ignoredWorlds.contains(worldName);
}
private boolean cannotBeTagged(Player player) {
if (this.config.admin.excludeAdminsFromCombat && player.hasPermission("eternalcombat.bypass")) {
return true;
}
if (this.config.admin.excludeAdminsFromCombat && player.isOp()) {
return true;
}
return this.config.admin.excludeCreativePlayersFromCombat && player.getGameMode() == GameMode.CREATIVE;
}
}
@@ -4,7 +4,8 @@ import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.region.Point;
import com.eternalcode.combat.region.Region;
import com.eternalcode.combat.region.RegionProvider;
import com.eternalcode.commons.scheduler.Scheduler;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import io.papermc.lib.PaperLib;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@@ -12,18 +13,18 @@ import java.util.Optional;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
public final class KnockbackService {
private final PluginConfig config;
private final Scheduler scheduler;
private final MinecraftScheduler scheduler;
private final RegionProvider regionProvider;
private final Map<UUID, Region> insideRegion = new HashMap<>();
public KnockbackService(PluginConfig config, Scheduler scheduler, RegionProvider regionProvider) {
public KnockbackService(PluginConfig config, MinecraftScheduler scheduler, RegionProvider regionProvider) {
this.config = config;
this.scheduler = scheduler;
this.regionProvider = regionProvider;
@@ -39,17 +40,20 @@ public final class KnockbackService {
}
insideRegion.put(player.getUniqueId(), region);
scheduler.runLater(() -> {
insideRegion.remove(player.getUniqueId());
Location playerLocation = player.getLocation();
if (!region.contains(playerLocation) && !regionProvider.isInRegion(playerLocation)) {
return;
}
Location location = generate(playerLocation, Point2D.from(region.getMin()), Point2D.from(region.getMax()));
scheduler.runLater(
player.getLocation(), () -> {
insideRegion.remove(player.getUniqueId());
Location playerLocation = player.getLocation();
if (!region.contains(playerLocation) && !regionProvider.isInRegion(playerLocation)) {
return;
}
player.teleport(location, PlayerTeleportEvent.TeleportCause.PLUGIN);
}, this.config.knockback.forceDelay);
Location location =
generate(playerLocation, Point2D.from(region.getMin()), Point2D.from(region.getMax()));
PaperLib.teleportAsync(player, location, TeleportCause.PLUGIN);
}, this.config.knockback.forceDelay);
}
private Location generate(Location playerLocation, Point2D minX, Point2D maxX) {
@@ -73,5 +77,4 @@ public final class KnockbackService {
player.setVelocity(knockbackVector.multiply(configuredVector));
}
}
@@ -85,7 +85,7 @@ public class WorldGuardRegionProvider implements RegionProvider {
@Nullable
private ProtectedRegion highestPriorityRegion(ApplicableRegionSet applicableRegions) {
return applicableRegions.getRegions().stream()
.min(Comparator.comparingInt(ProtectedRegion::getPriority))
.max(Comparator.comparingInt(ProtectedRegion::getPriority))
.orElse(null);
}
@@ -1,6 +1,7 @@
package com.eternalcode.combat.updater;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.commons.concurrent.FutureHandler;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.AudienceProvider;
import net.kyori.adventure.text.minimessage.MiniMessage;
@@ -9,12 +10,9 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import java.util.concurrent.CompletableFuture;
public class UpdaterNotificationController implements Listener {
private static final String NEW_VERSION_AVAILABLE = "<b><gradient:#8a1212:#fc6b03>EternalCombat:</gradient></b> <color:#fce303>New version of EternalCombat is available, please update!";
private static final String RECEIVE_UPDATES_PERMISSION = "eternalcombat.receiveupdates";
private final UpdaterService updaterService;
private final PluginConfig pluginConfig;
@@ -33,23 +31,21 @@ public class UpdaterNotificationController implements Listener {
Player player = event.getPlayer();
Audience audience = this.audienceProvider.player(player.getUniqueId());
if (!player.hasPermission(RECEIVE_UPDATES_PERMISSION) || !this.pluginConfig.settings.notifyAboutUpdates) {
if (!shouldNotify(player)) {
return;
}
CompletableFuture<Boolean> upToDate = this.updaterService.isUpToDate();
this.updaterService.checkForUpdate()
.thenAccept(result -> {
if (result.isUpdateAvailable()) {
audience.sendMessage(this.miniMessage.deserialize(NEW_VERSION_AVAILABLE));
}
})
.exceptionally(FutureHandler::handleException);
}
upToDate.whenComplete((isUpToDate, throwable) -> {
if (throwable != null) {
throwable.printStackTrace();
return;
}
if (!isUpToDate) {
audience.sendMessage(this.miniMessage.deserialize(NEW_VERSION_AVAILABLE));
}
});
private boolean shouldNotify(Player player) {
return player.hasPermission("eternalcombat.receiveupdates") && this.pluginConfig.settings.notifyAboutUpdates;
}
}
@@ -1,35 +1,33 @@
package com.eternalcode.combat.updater;
import com.eternalcode.gitcheck.GitCheck;
import com.eternalcode.gitcheck.GitCheckResult;
import com.eternalcode.gitcheck.git.GitRepository;
import com.eternalcode.gitcheck.git.GitTag;
import dev.rollczi.litecommands.shared.Lazy;
import com.eternalcode.commons.updater.UpdateResult;
import com.eternalcode.commons.updater.Version;
import com.eternalcode.commons.updater.impl.ModrinthUpdateChecker;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.bukkit.plugin.PluginDescriptionFile;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
public class UpdaterService {
private static final GitRepository GIT_REPOSITORY = GitRepository.of("EternalCodeTeam", "EternalCombat");
private static final String MODRINTH_PROJECT_ID = "EternalCombat";
private static final String CACHE_KEY = "modrinth-update";
private final GitCheck gitCheck = new GitCheck();
private final Lazy<GitCheckResult> gitCheckResult;
private final AsyncLoadingCache<String, UpdateResult> updateCache;
public UpdaterService(PluginDescriptionFile descriptionFile) {
this.gitCheckResult = new Lazy<>(() -> {
String version = descriptionFile.getVersion();
Version currentVersion = new Version(descriptionFile.getVersion());
ModrinthUpdateChecker updateChecker = new ModrinthUpdateChecker();
return this.gitCheck.checkRelease(GIT_REPOSITORY, GitTag.of("v" + version));
});
this.updateCache = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofHours(1))
.buildAsync(key -> updateChecker.check(MODRINTH_PROJECT_ID, currentVersion));
}
public CompletableFuture<Boolean> isUpToDate() {
return CompletableFuture.supplyAsync(() -> {
GitCheckResult result = this.gitCheckResult.get();
return result.isUpToDate();
});
CompletableFuture<UpdateResult> checkForUpdate() {
return this.updateCache.get(CACHE_KEY);
}
}
}
+5 -3
View File
@@ -1,5 +1,7 @@
org.gradle.configuration-cache=false
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.vfs.watch=false
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true
# Platforms
paperVersion=1.17,1.17.1,1.18,1.18.1,1.18.2,1.19,1.19.1,1.19.2,1.19.3,1.19.4,1.20,1.20.1,1.20.2,1.20.3,1.20.4,1.20.5,1.20.6,1.21,1.21.1,1.21.2,1.21.3,1.21.4,1.21.5,1.21.6,1.21.7,1.21.8,1.21.9,1.21.10,1.21.11
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
-3
View File
@@ -114,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@@ -172,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
Vendored
+1 -2
View File
@@ -70,11 +70,10 @@ goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell