fix: 1.21.11 Fabric support
This commit is contained in:
1 parent
fec77fba15
commit
9c6f94c10b
5 files changed
+102
-75
No files matched your search
@@ -37,7 +37,7 @@ dependencies {
|
|||||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "${rootProject.property("fabric_version")}"))
|
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "${rootProject.property("fabric_version")}"))
|
||||||
modImplementation(fabricApi.module("fabric-events-interaction-v0", "${rootProject.property("fabric_version")}"))
|
modImplementation(fabricApi.module("fabric-events-interaction-v0", "${rootProject.property("fabric_version")}"))
|
||||||
|
|
||||||
include(modImplementation("me.lucko:fabric-permissions-api:0.3.1")!!)
|
include(modImplementation("me.lucko:fabric-permissions-api:0.6.1")!!)
|
||||||
include(modImplementation("com.github.retrooper:packetevents-fabric:2.11.1+60a2c34-SNAPSHOT")!!)
|
include(modImplementation("com.github.retrooper:packetevents-fabric:2.11.1+60a2c34-SNAPSHOT")!!)
|
||||||
include(modImplementation("org.incendo:cloud-fabric:2.0.0-beta.15")!!)
|
include(modImplementation("org.incendo:cloud-fabric:2.0.0-beta.15")!!)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package me.caseload.knockbacksync.mixin;
|
||||||
|
|
||||||
|
import me.caseload.knockbacksync.callback.PlayerVelocityEvent;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.server.network.EntityTrackerEntry;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(EntityTrackerEntry.class)
|
||||||
|
public class EntityTrackerEntryMixin {
|
||||||
|
|
||||||
|
@Shadow @Final private Entity entity;
|
||||||
|
|
||||||
|
// We inject exactly where 'this.entity.knockedBack = false' is about to happen.
|
||||||
|
@Inject(method = "tick",
|
||||||
|
at = @At(value = "FIELD",
|
||||||
|
target = "Lnet/minecraft/entity/Entity;knockedBack:Z",
|
||||||
|
opcode = Opcodes.PUTFIELD),
|
||||||
|
cancellable = true)
|
||||||
|
private void onKnockbackSync(CallbackInfo ci) {
|
||||||
|
// This check ensures we are in the "if (entity.knockedBack)" block
|
||||||
|
// and operating on a Player.
|
||||||
|
if (this.entity instanceof ServerPlayerEntity serverPlayer) {
|
||||||
|
|
||||||
|
// 1. Capture the velocity CURRENTLY on the player
|
||||||
|
Vec3d currentVelocity = serverPlayer.getVelocity();
|
||||||
|
|
||||||
|
// 2. Fire the event
|
||||||
|
ActionResult result = PlayerVelocityEvent.EVENT.invoker().onVelocityChange(serverPlayer, currentVelocity);
|
||||||
|
|
||||||
|
if (result == ActionResult.FAIL) {
|
||||||
|
// CASE: CANCELLED
|
||||||
|
// We want to STOP the packet from sending.
|
||||||
|
// We also want to keep 'knockedBack' as true (technically),
|
||||||
|
// effectively acting like the block never happened.
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
else if (result == ActionResult.SUCCESS) {
|
||||||
|
// CASE: MODIFIED
|
||||||
|
// The event handler has already updated the player's velocity:
|
||||||
|
// player.setVelocity(newVel);
|
||||||
|
|
||||||
|
// We do NOT cancel. We let Vanilla proceed.
|
||||||
|
// Vanilla will:
|
||||||
|
// 1. Set knockedBack = false;
|
||||||
|
// 2. Create a NEW packet reading the current velocity (which is now your custom velocity).
|
||||||
|
// 3. Send it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,23 +14,50 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
@Mixin(PlayerEntity.class)
|
@Mixin(PlayerEntity.class)
|
||||||
public class PlayerMixin {
|
public class PlayerMixin {
|
||||||
@Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket;<init>(Lnet/minecraft/entity/Entity;)V"), cancellable = true)
|
|
||||||
private void onAttack(Entity target, CallbackInfo ci) {
|
|
||||||
if (target instanceof ServerPlayerEntity serverPlayer && target.velocityDirty) {
|
|
||||||
Vec3d velocity = target.getVelocity();
|
|
||||||
|
|
||||||
ActionResult result = PlayerVelocityEvent.EVENT.invoker().onVelocityChange(serverPlayer, velocity);
|
@Inject(method = "knockbackTarget",
|
||||||
|
at = @At(value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V"),
|
||||||
|
cancellable = true)
|
||||||
|
private void onKnockback(Entity target, float strength, Vec3d playerTargetVelocity, CallbackInfo ci) {
|
||||||
|
if (target instanceof ServerPlayerEntity serverPlayer && target.knockedBack) {
|
||||||
|
|
||||||
|
// 1. Get the "Proposed" Velocity (The knockback calculated lines above)
|
||||||
|
Vec3d proposedVelocity = target.getVelocity();
|
||||||
|
|
||||||
|
// 2. Fire the Event
|
||||||
|
ActionResult result = PlayerVelocityEvent.EVENT.invoker().onVelocityChange(serverPlayer, proposedVelocity);
|
||||||
|
|
||||||
if (result == ActionResult.FAIL) {
|
if (result == ActionResult.FAIL) {
|
||||||
target.velocityDirty = false;
|
// --- REPLICATING PAPER: CANCELLED ---
|
||||||
ci.cancel(); // Prevent sending the velocity packet
|
// In Paper: if (event.isCancelled()) { cancelled = true; }
|
||||||
} else if (result == ActionResult.SUCCESS) {
|
// In Paper: if (!cancelled) { sendPacket; cleanup; }
|
||||||
// Currently unnecessary since we do this in the handler, will move later
|
|
||||||
target.setVelocity(velocity);
|
// So, if cancelled, we stop EVERYTHING. We do not send packet, we do not reset velocity.
|
||||||
serverPlayer.networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(target));
|
ci.cancel();
|
||||||
target.velocityDirty = false;
|
return;
|
||||||
ci.cancel(); // Prevent sending the original velocity packet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result == ActionResult.SUCCESS) {
|
||||||
|
// --- REPLICATING PAPER: MODIFIED ---
|
||||||
|
// In Paper: if (!velocity.equals(event.getVelocity())) { player.setVelocity(...) }
|
||||||
|
// In Paper: if (!cancelled) { sendPacket; setDeltaMovement(currentMovement); }
|
||||||
|
|
||||||
|
// 1. The event listener should have already set the new velocity on the entity.
|
||||||
|
// 2. We must send a NEW packet (because the one on the stack is old).
|
||||||
|
serverPlayer.networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(target));
|
||||||
|
|
||||||
|
// 3. Replicate the Cleanup: Paper resets velocity to 'currentMovement' (playerTargetVelocity)
|
||||||
|
// This prevents the server from thinking the player is flying, maintaining Client Authority.
|
||||||
|
target.knockedBack = false;
|
||||||
|
target.setVelocity(playerTargetVelocity);
|
||||||
|
|
||||||
|
// 4. Cancel the original logic so Vanilla doesn't send the old packet or do double cleanup.
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE: PASS
|
||||||
|
// Vanilla behaves normally (Sends packet, does cleanup).
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package me.caseload.knockbacksync.mixin;
|
|
||||||
|
|
||||||
import me.caseload.knockbacksync.callback.PlayerVelocityEvent;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.server.network.EntityTrackerEntry;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.ActionResult;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(EntityTrackerEntry.class)
|
|
||||||
public class ServerEntityMixin {
|
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
private Entity entity;
|
|
||||||
|
|
||||||
// Velocity event
|
|
||||||
@Inject(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/Entity;velocityModified:Z", ordinal = 1), cancellable = true)
|
|
||||||
private void onSendChanges(CallbackInfo ci) {
|
|
||||||
if (this.entity.velocityDirty && this.entity instanceof ServerPlayerEntity player) {
|
|
||||||
Vec3d velocity = player.getVelocity();
|
|
||||||
|
|
||||||
ActionResult result = PlayerVelocityEvent.EVENT.invoker().onVelocityChange(player, velocity);
|
|
||||||
|
|
||||||
if (result == ActionResult.FAIL) {
|
|
||||||
this.entity.velocityDirty = false;
|
|
||||||
ci.cancel();
|
|
||||||
} else if (result == ActionResult.SUCCESS) {
|
|
||||||
// Currently unnecessary since we do this in the handler, will move later
|
|
||||||
player.setVelocity(velocity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom tick intervals
|
|
||||||
// @Shadow
|
|
||||||
// private int updateInterval;
|
|
||||||
|
|
||||||
// @Accessor("entity")
|
|
||||||
// Entity getEntity() {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Invoker("sendChanges")
|
|
||||||
// void invokeSendChanges() {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void setUpdateInterval(int interval) {
|
|
||||||
// this.updateInterval = interval;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ChunkMapMixin",
|
"ChunkMapMixin",
|
||||||
|
"EntityTrackerEntryMixin",
|
||||||
"PlayerMixin",
|
"PlayerMixin",
|
||||||
"ServerEntityMixin",
|
|
||||||
"TickRateManagerMixin"
|
"TickRateManagerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
|
|||||||
Reference in new issue
Block a user