Common:
- Fix NPE with combat task pings. All combat task management is now done in player netty threads. Bukkit: - Disable paper plugin remapping - Build a "lite" version that doesn't shade PacketEvents, allows multiple plugins to share PacketEvents or for you to update PacketEvents without rebuilding KnockbackSync Fabric: - Actually call onLoad() to init PE - Explicitly prevent loading on Client
This commit is contained in:
1 parent
bf609a1964
commit
a59ff6e625
12 files changed
+147
-74
No files matched your search
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Setup Gradle 8.10
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
gradle-version: "8.10" # Quotes required to prevent YAML converting to number
|
||||
gradle-version: "8.13" # Quotes required to prevent YAML converting to number
|
||||
|
||||
- name: Generate build number
|
||||
id: buildnumber
|
||||
@@ -53,39 +53,26 @@ jobs:
|
||||
# Ensure snapshot is set to false
|
||||
sed -i "s/val snapshot = .*/val snapshot = false/" build.gradle.kts
|
||||
|
||||
- name: Build with Gradle
|
||||
run: gradle clean build -x test
|
||||
- name: Build without PE shaded
|
||||
run: gradle build -PshadePE=false -x test
|
||||
env:
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
|
||||
- name: Rename shaded jar to overwrite non-shaded jar
|
||||
run: mv bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}-all.jar bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar
|
||||
- name: Build with PE shaded Gradle
|
||||
run: gradle build -PshadePE=true -x test
|
||||
env:
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
|
||||
# Download PaperSpigot (Choose version for reproducibility
|
||||
- name: Download PaperSpigot
|
||||
run: |
|
||||
mkdir -p paper-server/plugins
|
||||
curl -o paperclip.jar https://api.papermc.io/v2/projects/paper/versions/1.21.1/builds/120/downloads/paper-1.21.1-120.jar
|
||||
mv paperclip.jar paper-server/
|
||||
|
||||
# Copy Plugin into Plugins Folder and Start Server
|
||||
- name: Copy Plugin and Start Paper Server
|
||||
run: |
|
||||
cp bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar paper-server/plugins/
|
||||
cd paper-server
|
||||
# Start the server to remap the plugin
|
||||
timeout 60 java -Xms3G -Xmx3G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -jar -Dcom.mojang.eula.agree=true paperclip.jar --nogui || true
|
||||
|
||||
# Get the Hashes of the Original and Remapped JARs
|
||||
# Get the Hashes of the Original and Lite JARs
|
||||
- name: Calculate Hashes
|
||||
run: |
|
||||
# Calculate hash for the original JAR
|
||||
ORIGINAL_HASH=$(sha256sum bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar | awk '{print $1}')
|
||||
echo "ORIGINAL_HASH=$ORIGINAL_HASH" >> $GITHUB_ENV
|
||||
# Calculate hash for the remapped JAR
|
||||
REMAPPED_HASH=$(sha256sum paper-server/plugins/.paper-remapped/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar | awk '{print $1}')
|
||||
echo "REMAPPED_HASH=$REMAPPED_HASH" >> $GITHUB_ENV
|
||||
# Calculate hash for the remapped JAR
|
||||
BUKKIT_HASH=$(sha256sum bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar | awk '{print $1}')
|
||||
echo "BUKKIT_HASH=$BUKKIT_HASH" >> $GITHUB_ENV
|
||||
# Calculate hash for the lite JAR
|
||||
BUKKIT_LITE_HASH=$(sha256sum bukkit/build/libs/knockbacksync-bukkit-lite-${{ env.NEW_VERSION }}.jar | awk '{print $1}')
|
||||
echo "BUKKIT_LITE_HASH=$BUKKIT_LITE_HASH" >> $GITHUB_ENV
|
||||
# Calculate hash for the lite JAR
|
||||
FABRIC_HASH=$(sha256sum fabric/build/libs/knockbacksync-fabric-${{ env.NEW_VERSION }}.jar | awk '{print $1}')
|
||||
echo "FABRIC_HASH=$FABRIC_HASH" >> $GITHUB_ENV
|
||||
|
||||
@@ -111,8 +98,8 @@ jobs:
|
||||
}
|
||||
|
||||
# Add new hashes if they don't exist
|
||||
add_hash_if_new "${{ env.ORIGINAL_HASH }}"
|
||||
add_hash_if_new "${{ env.REMAPPED_HASH }}"
|
||||
add_hash_if_new "${{ env.BUKKIT_HASH }}"
|
||||
add_hash_if_new "${{ env.BUKKIT_LITE_HASH }}"
|
||||
add_hash_if_new "${{ env.FABRIC_HASH }}"
|
||||
|
||||
# Check if the file has changed
|
||||
@@ -143,23 +130,25 @@ jobs:
|
||||
# Clean up
|
||||
rm dev-builds.txt.original
|
||||
|
||||
- name: Create artifacts directory
|
||||
run: mkdir -p artifacts
|
||||
|
||||
- name: Copy bukkit artifact
|
||||
run: cp bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar artifacts/
|
||||
|
||||
- name: Copy fabric artifact
|
||||
run: cp fabric/build/libs/knockbacksync-fabric-${{ env.NEW_VERSION }}.jar artifacts/
|
||||
|
||||
- name: Zip the artifacts
|
||||
run: zip -r KnockbackSync-${{ env.NEW_VERSION }}.zip artifacts/*
|
||||
|
||||
- name: Upload artifacts zip
|
||||
- name: Upload Bukkit Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: KnockbackSync-${{ env.NEW_VERSION }}.zip
|
||||
path: KnockbackSync-${{ env.NEW_VERSION }}.zip
|
||||
name: knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar
|
||||
path: bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload Bukkit Lite Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: knockbacksync-bukkit-lite-${{ env.NEW_VERSION }}.jar
|
||||
path: bukkit/build/libs/knockbacksync-bukkit-lite-${{ env.NEW_VERSION }}.jar
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload Fabric Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: knockbacksync-fabric-${{ env.NEW_VERSION }}.jar
|
||||
path: fabric/build/libs/knockbacksync-fabric-${{ env.NEW_VERSION }}.jar
|
||||
retention-days: 90
|
||||
|
||||
- uses: Kir-Antipov/mc-publish@v3.3
|
||||
@@ -171,6 +160,7 @@ jobs:
|
||||
|
||||
files: |
|
||||
bukkit/build/libs/knockbacksync-bukkit-${{ env.NEW_VERSION }}.jar
|
||||
bukkit/build/libs/knockbacksync-bukkit-lite-${{ env.NEW_VERSION }}.jar
|
||||
|
||||
name: KnockbackSync-${{ env.NEW_VERSION }}
|
||||
version: ${{ env.NEW_VERSION }}
|
||||
|
||||
+5
-1
@@ -3,13 +3,17 @@ import java.io.ByteArrayOutputStream
|
||||
plugins {
|
||||
id("java")
|
||||
id("com.gradleup.shadow") version "8.3.3" apply false
|
||||
id("fabric-loom") version "1.8-SNAPSHOT" apply false
|
||||
id("fabric-loom") version "1.10.2" apply false
|
||||
}
|
||||
|
||||
val fullVersion = "1.3.5"
|
||||
val snapshot = true
|
||||
val githubRepo = System.getenv("GITHUB_REPOSITORY") ?: project.findProperty("githubRepo").toString()
|
||||
|
||||
extra["shadePE"] = project.findProperty("shadePE")?.toString()?.toBoolean()
|
||||
?: System.getenv("SHADE_PE")?.toBoolean()
|
||||
?: true
|
||||
|
||||
allprojects {
|
||||
fun getVersionMeta(includeHash: Boolean): String {
|
||||
if (!snapshot) {
|
||||
|
||||
+19
-3
@@ -4,8 +4,10 @@ plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
val shadePE: Boolean by rootProject.extra
|
||||
|
||||
base {
|
||||
archivesName.set("${rootProject.property("archives_base_name")}-bukkit")
|
||||
archivesName.set("${rootProject.property("archives_base_name")}-bukkit${if (shadePE) "" else "-lite"}")
|
||||
}
|
||||
|
||||
val shadeThisThing: Configuration by configurations.creating {
|
||||
@@ -31,13 +33,17 @@ dependencies {
|
||||
|
||||
compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
compileOnly("io.netty:netty-all:4.1.72.Final")
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.34")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.34")
|
||||
|
||||
shadeThisThing(implementation("org.kohsuke:github-api:1.326")!!)
|
||||
shadeThisThing(implementation("com.github.retrooper:packetevents-spigot:2.7.0-SNAPSHOT")!!)
|
||||
// shadeThisThing(implementation("net.kyori:adventure-platform-bukkit:4.3.4")!!)
|
||||
if (shadePE) {
|
||||
shadeThisThing(implementation("com.github.retrooper:packetevents-spigot:2.7.0-SNAPSHOT")!!)
|
||||
} else {
|
||||
compileOnly("com.github.retrooper:packetevents-spigot:2.7.0-SNAPSHOT")
|
||||
}
|
||||
shadeThisThing(implementation("org.incendo:cloud-paper:2.0.0-beta.10")!!)
|
||||
shadeThisThing(implementation("org.incendo:cloud-core:2.0.0")!!)
|
||||
|
||||
@@ -46,6 +52,13 @@ dependencies {
|
||||
}
|
||||
|
||||
tasks.withType<ShadowJar> {
|
||||
manifest {
|
||||
attributes["paperweight-mappings-namespace"] = "mojang"
|
||||
}
|
||||
|
||||
// Remove the -all suffix from the output JAR file name
|
||||
archiveClassifier.set("")
|
||||
|
||||
configurations = listOf(shadeThisThing)
|
||||
isEnableRelocation = false
|
||||
relocationPrefix = "${project.property("maven_group")}.${project.property("archives_base_name")}.shaded"
|
||||
@@ -58,11 +71,14 @@ tasks.build {
|
||||
tasks.processResources {
|
||||
from(project(":common").sourceSets.main.get().resources)
|
||||
inputs.property("version", project.version)
|
||||
inputs.property("shadePE", shadePE) // Add shadePE as an input to trigger reprocessing if it changes
|
||||
filteringCharset = "UTF-8"
|
||||
|
||||
|
||||
filesMatching("plugin.yml") {
|
||||
expand(
|
||||
"version" to project.version,
|
||||
"depends" to if (shadePE) "[]" else listOf("packetevents")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ api-version: '1.13' # We actually support 1.12.2, api-version was added later th
|
||||
authors: [ Caseload, Axionize ]
|
||||
description: Synchronizes player knockback for smoother gameplay.
|
||||
folia-supported: true
|
||||
depends: ${depends}
|
||||
permissions:
|
||||
knockbacksync.update:
|
||||
default: op
|
||||
|
||||
@@ -2,17 +2,23 @@ plugins {
|
||||
id("com.github.gmazzo.buildconfig") version "3.1.0"
|
||||
}
|
||||
|
||||
val shadePE: Boolean by rootProject.extra
|
||||
|
||||
dependencies {
|
||||
// True compileOnly deps
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
compileOnly("io.netty:netty-all:4.1.72.Final")
|
||||
compileOnly("org.projectlombok:lombok:1.18.34")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.34")
|
||||
|
||||
// Shaded in or bundled by platform-specific code
|
||||
implementation("com.github.retrooper:packetevents-api:2.7.0-SNAPSHOT")
|
||||
if (shadePE) {
|
||||
implementation("com.github.retrooper:packetevents-api:2.7.0-SNAPSHOT")
|
||||
} else {
|
||||
compileOnly("com.github.retrooper:packetevents-api:2.7.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
implementation("org.yaml:snakeyaml:2.0")
|
||||
// implementation("com.fasterxml.jackson.core:jackson-databind:2.17.2")
|
||||
// implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2")
|
||||
implementation("org.kohsuke:github-api:1.326") {
|
||||
exclude(group = "commons-io", module = "commons-io")
|
||||
exclude(group = "org.apache.commons", module = "commons-lang3")
|
||||
|
||||
@@ -25,9 +25,7 @@ public abstract class PlayerJoinQuitListener {
|
||||
if (playerData == null)
|
||||
return;
|
||||
|
||||
if (playerData.isInCombat())
|
||||
playerData.quitCombat();
|
||||
|
||||
playerData.quitCombat(true);
|
||||
PlayerDataManager.removePlayerData(uuid);
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,17 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CombatManager {
|
||||
|
||||
private static final Set<UUID> combatPlayers = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<@NotNull UUID> combatPlayers = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public static @NotNull Set<UUID> getPlayers() {
|
||||
public static @NotNull Set<@NotNull UUID> getPlayers() {
|
||||
return combatPlayers;
|
||||
}
|
||||
|
||||
public static void addPlayer(UUID uuid) {
|
||||
public static void addPlayer(@NotNull UUID uuid) {
|
||||
combatPlayers.add(uuid);
|
||||
}
|
||||
|
||||
public static void removePlayer(UUID uuid) {
|
||||
public static void removePlayer(@NotNull UUID uuid) {
|
||||
combatPlayers.remove(uuid);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import me.caseload.knockbacksync.event.events.ToggleOnOffEvent;
|
||||
import me.caseload.knockbacksync.manager.CombatManager;
|
||||
import me.caseload.knockbacksync.manager.ConfigManager;
|
||||
import me.caseload.knockbacksync.scheduler.AbstractTaskHandle;
|
||||
import me.caseload.knockbacksync.scheduler.NettyTaskHandle;
|
||||
import me.caseload.knockbacksync.util.MathUtil;
|
||||
import me.caseload.knockbacksync.util.data.Pair;
|
||||
import me.caseload.knockbacksync.world.PlatformWorld;
|
||||
@@ -32,8 +33,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Getter
|
||||
public class PlayerData {
|
||||
@@ -77,6 +80,7 @@ public class PlayerData {
|
||||
@Getter private final JitterCalculator jitterCalculator = new JitterCalculator();
|
||||
@Setter private double jitter;
|
||||
@Nullable private AbstractTaskHandle combatTask;
|
||||
@NotNull private final Object combatTaskLock = new Object(); // Lock object for synchronization
|
||||
@Nullable @Setter private Double ping, previousPing;
|
||||
@Nullable @Setter private Double verticalVelocity;
|
||||
@Nullable @Setter private Integer lastDamageTicks;
|
||||
@@ -292,28 +296,41 @@ public class PlayerData {
|
||||
return yAxis;
|
||||
}
|
||||
|
||||
public boolean isInCombat() {
|
||||
return combatTask != null;
|
||||
}
|
||||
|
||||
public void updateCombat() {
|
||||
if (isInCombat())
|
||||
combatTask.cancel();
|
||||
|
||||
combatTask = newCombatTask();
|
||||
CombatManager.addPlayer(uuid);
|
||||
Channel channel = (Channel) user.getChannel();
|
||||
channel.eventLoop().execute(() -> {
|
||||
if (combatTask != null) {
|
||||
combatTask.cancel();
|
||||
}
|
||||
combatTask = newCombatTask(channel);
|
||||
CombatManager.addPlayer(uuid);
|
||||
});
|
||||
}
|
||||
|
||||
public void quitCombat() {
|
||||
if (combatTask != null) combatTask.cancel(); // rarely throws NPE without null check
|
||||
combatTask = null;
|
||||
CombatManager.removePlayer(uuid);
|
||||
/**
|
||||
* Cancels the combatTask quit task. This prevents quitCombat() from being called later against a new combat task
|
||||
* Or against a player that has disconnected already
|
||||
* @param async Whether we are already in the players netty thread
|
||||
*/
|
||||
public void quitCombat(boolean async) {
|
||||
Channel channel = (Channel) user.getChannel();
|
||||
Runnable runnable = () -> {
|
||||
if (combatTask != null) {
|
||||
combatTask.cancel();
|
||||
combatTask = null;
|
||||
}
|
||||
CombatManager.removePlayer(uuid);
|
||||
};
|
||||
if (async) {
|
||||
channel.eventLoop().execute(runnable);
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AbstractTaskHandle newCombatTask() {
|
||||
return Base.INSTANCE.getScheduler().runTaskLaterAsynchronously(
|
||||
this::quitCombat, Base.INSTANCE.getConfigManager().getCombatTimer());
|
||||
private AbstractTaskHandle newCombatTask(Channel channel) {
|
||||
return new NettyTaskHandle(channel.eventLoop().schedule(() -> quitCombat(false), convertTicksToMilliseconds(Base.INSTANCE.getConfigManager().getCombatTimer()), TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
public ClientVersion getClientVersion() {
|
||||
@@ -360,4 +377,8 @@ public class PlayerData {
|
||||
throw new IllegalStateException("Unknown ping_strategy: " + pingStrategy);
|
||||
}
|
||||
}
|
||||
|
||||
private long convertTicksToMilliseconds(long ticks) {
|
||||
return ticks * 50;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package me.caseload.knockbacksync.scheduler;
|
||||
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
|
||||
public class NettyTaskHandle implements AbstractTaskHandle {
|
||||
|
||||
private final ScheduledFuture scheduledFuture;
|
||||
|
||||
public NettyTaskHandle(ScheduledFuture<?> scheduledFuture) {
|
||||
this.scheduledFuture = scheduledFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCancelled() {
|
||||
return scheduledFuture.isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
scheduledFuture.cancel(true);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
val shadePE: Boolean by rootProject.extra
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/knockbacksync.accesswidener")
|
||||
}
|
||||
@@ -57,6 +59,7 @@ dependencies {
|
||||
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
compileOnly("org.projectlombok:lombok:1.18.34")
|
||||
compileOnly("io.netty:netty-all:4.1.72.Final")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.34")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.caseload.knockbacksync;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
@@ -16,15 +17,23 @@ public class FabricLoaderMod implements PreLaunchEntrypoint, ModInitializer {
|
||||
|
||||
@Override
|
||||
public void onPreLaunch() {
|
||||
ensureServer();
|
||||
core.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ensureServer();
|
||||
core.enable();
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> {
|
||||
core.scheduler.shutdown();
|
||||
core.statsManager.getMetrics().shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
private void ensureServer() {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
throw new IllegalStateException("This mod can only be run on servers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@
|
||||
"icon": "assets/knockbacksync/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"preLaunch": [
|
||||
"me.caseload.knockbacksync.FabricLoaderMod"
|
||||
],
|
||||
"main": [
|
||||
"me.caseload.knockbacksync.FabricLoaderMod"
|
||||
]
|
||||
|
||||
Reference in new issue
Block a user