make everything work
This commit is contained in:
parent
38939750e6
commit
3a93c3beae
19 changed files with 346 additions and 391 deletions
|
@ -41,7 +41,7 @@ allprojects {
|
||||||
// for more information about repositories.
|
// for more information about repositories.
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
options.release = 17
|
options.release = 17
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
package ru.octol1ttle.knockdowns.common;
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import dev.architectury.event.EventResult;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
|
import net.minecraft.util.hit.HitResult;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
import ru.octol1ttle.knockdowns.common.events.KnockdownsClientEvents;
|
import ru.octol1ttle.knockdowns.common.events.KnockdownsClientEvents;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.RequestStartRevivingC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.StopRevivingC2SPacket;
|
||||||
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
|
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
|
||||||
import ru.octol1ttle.knockdowns.common.registries.KnockedDownSoundInstance;
|
import ru.octol1ttle.knockdowns.common.registries.KnockedDownSoundInstance;
|
||||||
|
|
||||||
public class KnockdownsClient {
|
public class KnockdownsClient {
|
||||||
|
@Nullable
|
||||||
|
public static Entity reviving;
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
KnockdownsClientEvents.registerCallbacks();
|
KnockdownsClientEvents.registerCallbacks();
|
||||||
}
|
}
|
||||||
|
@ -16,4 +29,35 @@ public class KnockdownsClient {
|
||||||
new KnockedDownSoundInstance(KnockdownsSoundEvents.KNOCKED_DOWN.get(), pos)
|
new KnockedDownSoundInstance(KnockdownsSoundEvents.KNOCKED_DOWN.get(), pos)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static EventResult onEntityUse(PlayerEntity player, Entity entity) {
|
||||||
|
if (KnockdownsCommon.isKnockedOrReviving(player) || !(entity instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) {
|
||||||
|
return EventResult.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
KnockdownsNetwork.sendToServer(new RequestStartRevivingC2SPacket(entity.getUuid()));
|
||||||
|
reviving = entity;
|
||||||
|
|
||||||
|
return EventResult.interruptTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onPlayerTick(PlayerEntity player) {
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
if (!player.equals(client.player) || reviving == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean playerKnocked = ((IKnockableDown) player).is_KnockedDown();
|
||||||
|
boolean revivingTargeted = client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.ENTITY
|
||||||
|
&& ((EntityHitResult) client.crosshairTarget).getEntity().getUuid().equals(reviving.getUuid());
|
||||||
|
|
||||||
|
if (!(reviving instanceof IKnockableDown knockable)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!knockable.is_KnockedDown() || playerKnocked || !revivingTargeted) {
|
||||||
|
KnockdownsNetwork.sendToServer(new StopRevivingC2SPacket(reviving.getUuid()));
|
||||||
|
reviving = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
package ru.octol1ttle.knockdowns.common;
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
import ru.octol1ttle.knockdowns.common.events.KnockdownsEvents;
|
import ru.octol1ttle.knockdowns.common.events.KnockdownsEvents;
|
||||||
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
|
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
|
||||||
|
|
||||||
public class KnockdownsCommon {
|
public class KnockdownsCommon {
|
||||||
public static final String MOD_ID = "knockdowns";
|
public static final String MOD_ID = "knockdowns";
|
||||||
|
public static final int REVIVE_WAIT_TIME = 10 * SharedConstants.TICKS_PER_SECOND;
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
KnockdownsSoundEvents.register();
|
KnockdownsSoundEvents.register();
|
||||||
KnockdownsNetwork.registerPackets();
|
KnockdownsNetwork.registerPackets();
|
||||||
KnockdownsEvents.registerCallbacks();
|
KnockdownsEvents.registerCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isKnockedOrReviving(PlayerEntity player) {
|
||||||
|
return player instanceof IKnockableDown knockable && (knockable.is_KnockedDown() || knockable.is_Reviving());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
package ru.octol1ttle.knockdowns.common.api;
|
package ru.octol1ttle.knockdowns.common.api;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface IKnockableDown {
|
public interface IKnockableDown {
|
||||||
boolean knockdowns$isKnockedDown();
|
boolean is_KnockedDown();
|
||||||
|
|
||||||
void knockdowns$setKnockedDown(boolean knockedDown);
|
void set_KnockedDown(boolean knockedDown);
|
||||||
|
|
||||||
boolean knockdowns$isBeingRevived();
|
int get_ReviverCount();
|
||||||
|
|
||||||
void knockdowns$setBeingRevived(boolean beingRevived);
|
void set_ReviverCount(int reviverCount);
|
||||||
|
|
||||||
UUID knockdowns$getUuid();
|
boolean is_Reviving();
|
||||||
|
|
||||||
|
void set_Reviving(boolean reviving);
|
||||||
|
|
||||||
|
int get_ReviveTimer();
|
||||||
|
|
||||||
|
void set_ReviveTimer(int reviveTimer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,105 +1,44 @@
|
||||||
package ru.octol1ttle.knockdowns.common.events;
|
package ru.octol1ttle.knockdowns.common.events;
|
||||||
|
|
||||||
import dev.architectury.event.EventResult;
|
|
||||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||||
import dev.architectury.event.events.client.ClientPlayerEvent;
|
|
||||||
import dev.architectury.event.events.client.ClientTickEvent;
|
|
||||||
import dev.architectury.event.events.common.InteractionEvent;
|
|
||||||
import java.util.UUID;
|
|
||||||
import net.minecraft.SharedConstants;
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import ru.octol1ttle.knockdowns.common.KnockdownsClient;
|
||||||
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.KnockedDownStatusPacket;
|
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.ReviveStatusPacket;
|
|
||||||
|
|
||||||
public class KnockdownsClientEvents {
|
public class KnockdownsClientEvents {
|
||||||
private static final int REVIVAL_WAIT_TIME = 10 * SharedConstants.TICKS_PER_SECOND;
|
|
||||||
private static IKnockableDown reviving = null;
|
|
||||||
private static int revivalTimer = -1;
|
|
||||||
|
|
||||||
public static void registerCallbacks() {
|
public static void registerCallbacks() {
|
||||||
registerOnClientPlayerJoin();
|
|
||||||
registerOnEntityUse();
|
|
||||||
registerOnWorldTick();
|
|
||||||
registerOnHudRender();
|
registerOnHudRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerOnClientPlayerJoin() {
|
|
||||||
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
|
|
||||||
UUID playerUuid = player.getUuid();
|
|
||||||
KnockdownsNetwork.sendToServer(new KnockedDownStatusPacket.RequestC2S(playerUuid));
|
|
||||||
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.RequestC2S(playerUuid));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerOnEntityUse() {
|
|
||||||
InteractionEvent.INTERACT_ENTITY.register((player, entity, hand) -> {
|
|
||||||
if (!player.getWorld().isClient() || !(entity instanceof IKnockableDown knockableEntity) || !knockableEntity.knockdowns$isKnockedDown()
|
|
||||||
|| knockableEntity.knockdowns$isBeingRevived()) {
|
|
||||||
return EventResult.pass();
|
|
||||||
}
|
|
||||||
|
|
||||||
IKnockableDown self = (IKnockableDown) player;
|
|
||||||
if (self.knockdowns$isKnockedDown()) {
|
|
||||||
return EventResult.interruptFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
knockableEntity.knockdowns$setBeingRevived(true);
|
|
||||||
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.SendC2S(entity.getUuid(), true));
|
|
||||||
|
|
||||||
reviving = knockableEntity;
|
|
||||||
revivalTimer = REVIVAL_WAIT_TIME;
|
|
||||||
|
|
||||||
return EventResult.interruptTrue();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerOnWorldTick() {
|
|
||||||
ClientTickEvent.ClientLevel.CLIENT_LEVEL_POST.register(world -> {
|
|
||||||
boolean revived = false;
|
|
||||||
revivalTimer--;
|
|
||||||
if (revivalTimer <= 0) {
|
|
||||||
revivalTimer = -1;
|
|
||||||
revived = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reviving == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HitResult crosshairTarget = MinecraftClient.getInstance().crosshairTarget;
|
|
||||||
if (revived || crosshairTarget == null || crosshairTarget.getType() != HitResult.Type.ENTITY
|
|
||||||
|| !((EntityHitResult) crosshairTarget).getEntity().getUuid().equals(reviving.knockdowns$getUuid())) {
|
|
||||||
reviving.knockdowns$setBeingRevived(false);
|
|
||||||
|
|
||||||
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.SendC2S(reviving.knockdowns$getUuid(), false));
|
|
||||||
if (revived) {
|
|
||||||
reviving.knockdowns$setKnockedDown(false);
|
|
||||||
|
|
||||||
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.RevivedC2S(reviving.knockdowns$getUuid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
reviving = null;
|
|
||||||
revivalTimer = -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerOnHudRender() {
|
private static void registerOnHudRender() {
|
||||||
ClientGuiEvent.RENDER_HUD.register((drawContext, tickDelta) -> {
|
ClientGuiEvent.RENDER_HUD.register((drawContext, tickDelta) -> {
|
||||||
if (revivalTimer == -1) {
|
IKnockableDown reviving = (IKnockableDown) KnockdownsClient.reviving;
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
if (reviving == null) {
|
||||||
|
reviving = (IKnockableDown) client.player;
|
||||||
|
if (reviving == null || reviving.get_ReviverCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextRenderer renderer = MinecraftClient.getInstance().textRenderer;
|
TextRenderer renderer = client.textRenderer;
|
||||||
String text = String.format("%.1f", revivalTimer / (float) SharedConstants.TICKS_PER_SECOND);
|
|
||||||
int x = (drawContext.getScaledWindowWidth() - renderer.getWidth(text)) / 2;
|
|
||||||
|
|
||||||
drawContext.drawTextWithShadow(renderer, text, x, drawContext.getScaledWindowHeight() / 2 + 15, 0xFFFFFF);
|
String timerText = String.format("%.1f", reviving.get_ReviveTimer() / (float) SharedConstants.TICKS_PER_SECOND);
|
||||||
|
int timerX = (drawContext.getScaledWindowWidth() - renderer.getWidth(timerText)) / 2;
|
||||||
|
|
||||||
|
int reviverCount = reviving.get_ReviverCount();
|
||||||
|
Integer color = reviverCount > 1 ? Formatting.GREEN.getColorValue() : Formatting.WHITE.getColorValue();
|
||||||
|
|
||||||
|
String reviverCountText = "x" + reviverCount;
|
||||||
|
int reviveCountX = (drawContext.getScaledWindowWidth() - renderer.getWidth(reviverCountText)) / 2;
|
||||||
|
|
||||||
|
if (color != null) {
|
||||||
|
drawContext.drawTextWithShadow(renderer, timerText, timerX, drawContext.getScaledWindowHeight() / 2 + 5, color);
|
||||||
|
drawContext.drawTextWithShadow(renderer, reviverCountText, reviveCountX, drawContext.getScaledWindowHeight() / 2 + 14, color);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,46 +5,50 @@ import dev.architectury.event.EventResult;
|
||||||
import dev.architectury.event.events.common.EntityEvent;
|
import dev.architectury.event.events.common.EntityEvent;
|
||||||
import dev.architectury.event.events.common.InteractionEvent;
|
import dev.architectury.event.events.common.InteractionEvent;
|
||||||
import dev.architectury.event.events.common.PlayerEvent;
|
import dev.architectury.event.events.common.PlayerEvent;
|
||||||
|
import dev.architectury.event.events.common.TickEvent;
|
||||||
|
import java.util.Objects;
|
||||||
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableTextContent;
|
import net.minecraft.text.TranslatableTextContent;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.world.GameRules;
|
import ru.octol1ttle.knockdowns.common.KnockdownsClient;
|
||||||
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.KnockedDownStatusPacket;
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.PlayKnockedDownSoundS2CPacket;
|
import ru.octol1ttle.knockdowns.common.network.packets.PlayKnockedDownSoundS2CPacket;
|
||||||
|
|
||||||
public class KnockdownsEvents {
|
public class KnockdownsEvents {
|
||||||
|
private static final float KNOCKED_DOWN_TIMER = 50.0f;
|
||||||
|
|
||||||
public static void registerCallbacks() {
|
public static void registerCallbacks() {
|
||||||
registerOnLivingDeath();
|
registerOnLivingDeath();
|
||||||
|
registerOnPlayerTick();
|
||||||
registerOnPlayerInteractions();
|
registerOnPlayerInteractions();
|
||||||
|
registerOnEntityUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerOnLivingDeath() {
|
private static void registerOnLivingDeath() {
|
||||||
EntityEvent.LIVING_DEATH.register((entity, source) -> {
|
EntityEvent.LIVING_DEATH.register((entity, source) -> {
|
||||||
if (!(entity instanceof IKnockableDown knockableDown) || knockableDown.knockdowns$isKnockedDown()) {
|
if (entity.getWorld().isClient() || !(entity instanceof IKnockableDown knockable) || knockable.is_KnockedDown()) {
|
||||||
return EventResult.pass();
|
return EventResult.pass();
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) entity;
|
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) entity;
|
||||||
// TODO: timer
|
|
||||||
if (!serverPlayer.getWorld().getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) {
|
entity.clearStatusEffects();
|
||||||
serverPlayer.getInventory().dropAll();
|
|
||||||
}
|
|
||||||
entity.setHealth(1.0f);
|
|
||||||
entity.setInvulnerable(true);
|
entity.setInvulnerable(true);
|
||||||
entity.setGlowing(true);
|
entity.setGlowing(true);
|
||||||
entity.setAir(entity.getMaxAir());
|
entity.setHealth(entity.getMaxHealth());
|
||||||
entity.extinguish();
|
entity.extinguish();
|
||||||
|
entity.setAir(entity.getMaxAir());
|
||||||
entity.setFrozenTicks(0);
|
entity.setFrozenTicks(0);
|
||||||
entity.setOnFire(false);
|
serverPlayer.stopFallFlying();
|
||||||
entity.clearStatusEffects();
|
|
||||||
|
|
||||||
knockableDown.knockdowns$setKnockedDown(true);
|
knockable.set_KnockedDown(true);
|
||||||
|
knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME);
|
||||||
|
|
||||||
KnockdownsNetwork.sendToListenersAndSelf(serverPlayer, new KnockedDownStatusPacket.SendS2C(serverPlayer.getUuid(), true));
|
|
||||||
KnockdownsNetwork.sendToWorld(serverPlayer.getServerWorld(), new PlayKnockedDownSoundS2CPacket(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ()));
|
KnockdownsNetwork.sendToWorld(serverPlayer.getServerWorld(), new PlayKnockedDownSoundS2CPacket(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ()));
|
||||||
|
|
||||||
TranslatableTextContent content = (TranslatableTextContent) entity.getDamageTracker().getDeathMessage().getContent();
|
TranslatableTextContent content = (TranslatableTextContent) entity.getDamageTracker().getDeathMessage().getContent();
|
||||||
|
@ -58,30 +62,69 @@ public class KnockdownsEvents {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void registerOnPlayerTick() {
|
||||||
|
TickEvent.PLAYER_POST.register(player -> {
|
||||||
|
if (player.getWorld().isClient()) {
|
||||||
|
KnockdownsClient.onPlayerTick(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(player instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (knockable.get_ReviverCount() > 0) {
|
||||||
|
knockable.set_ReviveTimer(knockable.get_ReviveTimer() - knockable.get_ReviverCount());
|
||||||
|
|
||||||
|
if (knockable.get_ReviveTimer() <= 0) {
|
||||||
|
knockable.set_KnockedDown(false);
|
||||||
|
knockable.set_ReviverCount(0);
|
||||||
|
knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME);
|
||||||
|
|
||||||
|
player.setInvulnerable(false);
|
||||||
|
player.setGlowing(false);
|
||||||
|
player.setHealth(6.0f);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
knockable.set_ReviveTimer(Math.min(KnockdownsCommon.REVIVE_WAIT_TIME, knockable.get_ReviveTimer() + 2));
|
||||||
|
|
||||||
|
if (player.age % 20 == 0) {
|
||||||
|
player.setInvulnerable(false);
|
||||||
|
DamageSource recent = player.getRecentDamageSource();
|
||||||
|
player.damage(Objects.requireNonNullElse(recent, player.getDamageSources().generic()), player.getMaxHealth() / KNOCKED_DOWN_TIMER);
|
||||||
|
player.velocityModified = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static void registerOnPlayerInteractions() {
|
private static void registerOnPlayerInteractions() {
|
||||||
InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
|
InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
|
||||||
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
|
if (KnockdownsCommon.isKnockedOrReviving(player)) {
|
||||||
return EventResult.interruptFalse();
|
return EventResult.interruptFalse();
|
||||||
}
|
}
|
||||||
return EventResult.pass();
|
return EventResult.pass();
|
||||||
});
|
});
|
||||||
PlayerEvent.ATTACK_ENTITY.register((player, world, hand, entity, hitResult) -> {
|
PlayerEvent.ATTACK_ENTITY.register((player, world, hand, entity, hitResult) -> {
|
||||||
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
|
if (KnockdownsCommon.isKnockedOrReviving(player)) {
|
||||||
return EventResult.interruptFalse();
|
return EventResult.interruptFalse();
|
||||||
}
|
}
|
||||||
return EventResult.pass();
|
return EventResult.pass();
|
||||||
});
|
});
|
||||||
InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> {
|
InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> {
|
||||||
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
|
if (KnockdownsCommon.isKnockedOrReviving(player)) {
|
||||||
return CompoundEventResult.interruptFalse(hand == Hand.MAIN_HAND ? player.getMainHandStack() : player.getOffHandStack());
|
return CompoundEventResult.interruptFalse(hand == Hand.MAIN_HAND ? player.getMainHandStack() : player.getOffHandStack());
|
||||||
}
|
}
|
||||||
return CompoundEventResult.pass();
|
return CompoundEventResult.pass();
|
||||||
});
|
});
|
||||||
InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
|
InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
|
||||||
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
|
if (KnockdownsCommon.isKnockedOrReviving(player)) {
|
||||||
return EventResult.interruptFalse();
|
return EventResult.interruptFalse();
|
||||||
}
|
}
|
||||||
return EventResult.pass();
|
return EventResult.pass();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void registerOnEntityUse() {
|
||||||
|
InteractionEvent.INTERACT_ENTITY.register((player, entity, hand)
|
||||||
|
-> player.getWorld().isClient() ? KnockdownsClient.onEntityUse(player, entity) : EventResult.pass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.mixin;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
|
@Mixin(LivingEntity.class)
|
||||||
|
public abstract class LivingEntityMixin {
|
||||||
|
@ModifyReturnValue(method = "canTarget(Lnet/minecraft/entity/LivingEntity;)Z", at = @At("RETURN"))
|
||||||
|
private boolean dontTargetKnockedPlayers(boolean original, LivingEntity target) {
|
||||||
|
return original && !(target instanceof IKnockableDown knockable && knockable.is_KnockedDown());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
|
@Mixin(MobEntity.class)
|
||||||
|
public abstract class MobEntityMixin {
|
||||||
|
@Inject(method = "setTarget", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void setTarget(LivingEntity target, CallbackInfo ci) {
|
||||||
|
if (target instanceof IKnockableDown knockable && knockable.is_KnockedDown()) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,70 +2,114 @@ package ru.octol1ttle.knockdowns.common.mixin;
|
||||||
|
|
||||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||||
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
import java.util.UUID;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.data.DataTracker;
|
||||||
|
import net.minecraft.entity.data.TrackedData;
|
||||||
|
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.world.World;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
|
@SuppressWarnings("WrongEntityDataParameterClass")
|
||||||
@Mixin(PlayerEntity.class)
|
@Mixin(PlayerEntity.class)
|
||||||
public abstract class PlayerEntityMixin implements IKnockableDown {
|
public abstract class PlayerEntityMixin extends Entity implements IKnockableDown {
|
||||||
@Unique
|
@Unique
|
||||||
private boolean knockdowns$knockedDown;
|
private static final TrackedData<Boolean> KNOCKED_DOWN = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||||
@Unique
|
@Unique
|
||||||
private boolean knockdowns$beingRevived;
|
private static final TrackedData<Boolean> IS_REVIVING = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||||
|
@Unique
|
||||||
|
private static final TrackedData<Integer> REVIVER_COUNT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
@Unique
|
||||||
|
private static final TrackedData<Integer> REVIVE_TIMER = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
|
||||||
|
private PlayerEntityMixin(EntityType<?> type, World world) {
|
||||||
|
super(type, world);
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
@ModifyExpressionValue(method = "updatePose", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;isSwimming()Z"))
|
@ModifyExpressionValue(method = "updatePose", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;isSwimming()Z"))
|
||||||
private boolean enterSwimmingIfKnockedDown(boolean original) {
|
private boolean enterSwimmingIfKnockedDown(boolean original) {
|
||||||
PlayerEntity player = (PlayerEntity)(Object)this;
|
return original || this.is_KnockedDown();
|
||||||
if (!(player instanceof IKnockableDown knockableDown)) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return original || knockableDown.knockdowns$isKnockedDown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModifyReturnValue(method = "canFoodHeal", at = @At("RETURN"))
|
@ModifyReturnValue(method = "canFoodHeal", at = @At("RETURN"))
|
||||||
private boolean dontHealIfKnockedDown(boolean original) {
|
private boolean dontHealIfKnockedDown(boolean original) {
|
||||||
return original && !this.knockdowns$isKnockedDown();
|
return original && !this.is_KnockedDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "checkFallFlying", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void dontOpenElytraIfKnockedDown(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (this.is_KnockedDown()) {
|
||||||
|
cir.setReturnValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "initDataTracker", at = @At("TAIL"))
|
||||||
|
private void initCustomDataTracker(CallbackInfo ci) {
|
||||||
|
this.dataTracker.startTracking(KNOCKED_DOWN, false);
|
||||||
|
this.dataTracker.startTracking(IS_REVIVING, false);
|
||||||
|
this.dataTracker.startTracking(REVIVER_COUNT, 0);
|
||||||
|
this.dataTracker.startTracking(REVIVE_TIMER, KnockdownsCommon.REVIVE_WAIT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
|
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
|
||||||
public void readKnockedDownFromNbt(NbtCompound nbt, CallbackInfo ci) {
|
private void readKnockedDownFromNbt(NbtCompound nbt, CallbackInfo ci) {
|
||||||
this.knockdowns$knockedDown = nbt.getBoolean("KnockedDown");
|
this.set_KnockedDown(nbt.getBoolean("KnockedDown"));
|
||||||
|
this.set_ReviveTimer(nbt.getInt("ReviveTimer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
|
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
|
||||||
public void writeKnockedDownToNbt(NbtCompound nbt, CallbackInfo ci) {
|
private void writeKnockedDownToNbt(NbtCompound nbt, CallbackInfo ci) {
|
||||||
nbt.putBoolean("KnockedDown", this.knockdowns$knockedDown);
|
nbt.putBoolean("KnockedDown", this.is_KnockedDown());
|
||||||
|
nbt.putInt("ReviveTimer", this.get_ReviveTimer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean knockdowns$isKnockedDown() {
|
public boolean is_KnockedDown() {
|
||||||
return knockdowns$knockedDown;
|
return this.dataTracker.get(KNOCKED_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void knockdowns$setKnockedDown(boolean knockedDown) {
|
public void set_KnockedDown(boolean knockedDown) {
|
||||||
this.knockdowns$knockedDown = knockedDown;
|
this.dataTracker.set(KNOCKED_DOWN, knockedDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean knockdowns$isBeingRevived() {
|
public boolean is_Reviving() {
|
||||||
return knockdowns$beingRevived;
|
return this.dataTracker.get(IS_REVIVING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void knockdowns$setBeingRevived(boolean beingRevived) {
|
public void set_Reviving(boolean reviving) {
|
||||||
this.knockdowns$beingRevived = beingRevived;
|
this.dataTracker.set(IS_REVIVING, reviving);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID knockdowns$getUuid() {
|
public int get_ReviverCount() {
|
||||||
return ((PlayerEntity)(Object)this).getUuid();
|
return this.dataTracker.get(REVIVER_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set_ReviverCount(int reviverCount) {
|
||||||
|
this.dataTracker.set(REVIVER_COUNT, reviverCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int get_ReviveTimer() {
|
||||||
|
return this.dataTracker.get(REVIVE_TIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set_ReviveTimer(int reviveTimer) {
|
||||||
|
this.dataTracker.set(REVIVE_TIMER, reviveTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,9 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
@Mixin(ClientPlayerEntity.class)
|
@Mixin(ClientPlayerEntity.class)
|
||||||
public abstract class ClientPlayerEntityMixin {
|
public abstract class ClientPlayerEntityMixin implements IKnockableDown {
|
||||||
@ModifyReturnValue(method = "shouldSlowDown", at = @At("RETURN"))
|
@ModifyReturnValue(method = "shouldSlowDown", at = @At("RETURN"))
|
||||||
private boolean shouldSlowDown(boolean original) {
|
private boolean shouldSlowDown(boolean original) {
|
||||||
IKnockableDown self = (IKnockableDown) this;
|
return original || this.is_KnockedDown();
|
||||||
return original || self.knockdowns$isKnockedDown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,32 +2,22 @@ package ru.octol1ttle.knockdowns.common.network;
|
||||||
|
|
||||||
import dev.architectury.networking.NetworkChannel;
|
import dev.architectury.networking.NetworkChannel;
|
||||||
import dev.architectury.networking.NetworkManager;
|
import dev.architectury.networking.NetworkManager;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.packet.Packet;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.server.world.EntityTrackingListener;
|
|
||||||
import net.minecraft.server.world.ServerChunkManager;
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
|
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.KnockedDownStatusPacket;
|
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.PlayKnockedDownSoundS2CPacket;
|
import ru.octol1ttle.knockdowns.common.network.packets.PlayKnockedDownSoundS2CPacket;
|
||||||
import ru.octol1ttle.knockdowns.common.network.packets.ReviveStatusPacket;
|
import ru.octol1ttle.knockdowns.common.network.packets.RequestStartRevivingC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.StopRevivingC2SPacket;
|
||||||
|
|
||||||
public class KnockdownsNetwork {
|
public class KnockdownsNetwork {
|
||||||
private static final NetworkChannel CHANNEL = NetworkChannel.create(new Identifier(KnockdownsCommon.MOD_ID, "main"));
|
private static final NetworkChannel CHANNEL = NetworkChannel.create(new Identifier(KnockdownsCommon.MOD_ID, "main"));
|
||||||
public static void registerPackets() {
|
public static void registerPackets() {
|
||||||
CHANNEL.register(KnockedDownStatusPacket.SendS2C.class, KnockedDownStatusPacket.SendS2C::encode, KnockedDownStatusPacket.SendS2C::new, KnockedDownStatusPacket.SendS2C::apply);
|
|
||||||
CHANNEL.register(KnockedDownStatusPacket.RequestC2S.class, KnockedDownStatusPacket.RequestC2S::encode, KnockedDownStatusPacket.RequestC2S::new, KnockedDownStatusPacket.RequestC2S::apply);
|
|
||||||
|
|
||||||
CHANNEL.register(PlayKnockedDownSoundS2CPacket.class, PlayKnockedDownSoundS2CPacket::encode, PlayKnockedDownSoundS2CPacket::new, PlayKnockedDownSoundS2CPacket::apply);
|
CHANNEL.register(PlayKnockedDownSoundS2CPacket.class, PlayKnockedDownSoundS2CPacket::encode, PlayKnockedDownSoundS2CPacket::new, PlayKnockedDownSoundS2CPacket::apply);
|
||||||
|
CHANNEL.register(RequestStartRevivingC2SPacket.class, RequestStartRevivingC2SPacket::encode, RequestStartRevivingC2SPacket::new, RequestStartRevivingC2SPacket::apply);
|
||||||
CHANNEL.register(ReviveStatusPacket.SendS2C.class, ReviveStatusPacket.SendS2C::encode, ReviveStatusPacket.SendS2C::new, ReviveStatusPacket.SendS2C::apply);
|
CHANNEL.register(StopRevivingC2SPacket.class, StopRevivingC2SPacket::encode, StopRevivingC2SPacket::new, StopRevivingC2SPacket::apply);
|
||||||
CHANNEL.register(ReviveStatusPacket.SendC2S.class, ReviveStatusPacket.SendC2S::encode, ReviveStatusPacket.SendC2S::new, ReviveStatusPacket.SendC2S::apply);
|
|
||||||
CHANNEL.register(ReviveStatusPacket.RequestC2S.class, ReviveStatusPacket.RequestC2S::encode, ReviveStatusPacket.RequestC2S::new, ReviveStatusPacket.RequestC2S::apply);
|
|
||||||
CHANNEL.register(ReviveStatusPacket.RevivedC2S.class, ReviveStatusPacket.RevivedC2S::encode, ReviveStatusPacket.RevivedC2S::new, ReviveStatusPacket.RevivedC2S::apply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void sendToServer(T message) {
|
public static <T> void sendToServer(T message) {
|
||||||
|
@ -52,30 +42,6 @@ public class KnockdownsNetwork {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: PR to Architectury API
|
|
||||||
public static <T> void sendToListeners(Entity entity, T message) {
|
|
||||||
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
|
|
||||||
Class<?> messageClass = message.getClass();
|
|
||||||
|
|
||||||
sendToListeners(entity, packet, messageClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sendToListeners(Entity entity, Packet<?> packet, Class<?> messageClass) {
|
|
||||||
ServerChunkManager chunkManager = (ServerChunkManager) entity.getWorld().getChunkManager();
|
|
||||||
ThreadedAnvilChunkStorage.EntityTracker entityTracker = chunkManager.threadedAnvilChunkStorage.entityTrackers.get(entity.getId());
|
|
||||||
|
|
||||||
for (EntityTrackingListener listener : entityTracker.listeners) {
|
|
||||||
sendToPlayer(listener.getPlayer(), packet, messageClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void sendToListenersAndSelf(PlayerEntity player, T message) {
|
|
||||||
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
|
|
||||||
Class<?> messageClass = message.getClass();
|
|
||||||
sendToPlayer(player, packet, messageClass);
|
|
||||||
sendToListeners(player, packet, messageClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void sendToWorld(ServerWorld world, T message) {
|
public static <T> void sendToWorld(ServerWorld world, T message) {
|
||||||
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
|
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
|
||||||
Class<?> messageClass = message.getClass();
|
Class<?> messageClass = message.getClass();
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
package ru.octol1ttle.knockdowns.common.network.packets;
|
|
||||||
|
|
||||||
import dev.architectury.networking.NetworkManager;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
|
||||||
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
|
||||||
|
|
||||||
public class KnockedDownStatusPacket {
|
|
||||||
public static class SendS2C extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
private final boolean knockedDown;
|
|
||||||
|
|
||||||
public SendS2C(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid(), buf.readBoolean());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SendS2C(UUID playerUuid, boolean knockedDown) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
this.knockedDown = knockedDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
buf.writeBoolean(this.knockedDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
if (knockableDown != null) {
|
|
||||||
knockableDown.knockdowns$setKnockedDown(this.knockedDown);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RequestC2S extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
|
|
||||||
public RequestC2S(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestC2S(UUID playerUuid) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
if (knockableDown != null) {
|
|
||||||
KnockdownsNetwork.sendToPlayer(context.getPlayer(), new SendS2C(this.playerUuid, knockableDown.knockdowns$isKnockedDown()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets;
|
||||||
|
|
||||||
|
import dev.architectury.networking.NetworkManager;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
|
public class RequestStartRevivingC2SPacket extends KnockdownsPacket {
|
||||||
|
private final UUID targetUuid;
|
||||||
|
|
||||||
|
public RequestStartRevivingC2SPacket(PacketByteBuf buf) {
|
||||||
|
this(buf.readUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequestStartRevivingC2SPacket(UUID targetUuid) {
|
||||||
|
this.targetUuid = targetUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(PacketByteBuf buf) {
|
||||||
|
buf.writeUuid(this.targetUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
||||||
|
NetworkManager.PacketContext context = contextSupplier.get();
|
||||||
|
context.queue(() -> {
|
||||||
|
PlayerEntity player = context.getPlayer();
|
||||||
|
IKnockableDown playerKnockable = (IKnockableDown) player;
|
||||||
|
IKnockableDown targetKnockable = (IKnockableDown) player.getWorld().getPlayerByUuid(this.targetUuid);
|
||||||
|
if (!playerKnockable.is_Reviving() && targetKnockable != null && targetKnockable.is_KnockedDown()) {
|
||||||
|
playerKnockable.set_Reviving(true);
|
||||||
|
targetKnockable.set_ReviverCount(targetKnockable.get_ReviverCount() + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,138 +0,0 @@
|
||||||
package ru.octol1ttle.knockdowns.common.network.packets;
|
|
||||||
|
|
||||||
import dev.architectury.networking.NetworkManager;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
|
||||||
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
|
||||||
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
|
||||||
|
|
||||||
public class ReviveStatusPacket {
|
|
||||||
public static class SendS2C extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
private final boolean beingRevived;
|
|
||||||
|
|
||||||
public SendS2C(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid(), buf.readBoolean());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SendS2C(UUID playerUuid, boolean beingRevived) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
this.beingRevived = beingRevived;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
buf.writeBoolean(this.beingRevived);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
if (knockableDown != null) {
|
|
||||||
knockableDown.knockdowns$setBeingRevived(this.beingRevived);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SendC2S extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
private final boolean beingRevived;
|
|
||||||
|
|
||||||
public SendC2S(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid(), buf.readBoolean());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SendC2S(UUID playerUuid, boolean beingRevived) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
this.beingRevived = beingRevived;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
buf.writeBoolean(this.beingRevived);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
if (knockableDown != null) {
|
|
||||||
knockableDown.knockdowns$setBeingRevived(this.beingRevived);
|
|
||||||
KnockdownsNetwork.sendToListenersAndSelf(context.getPlayer(), new ReviveStatusPacket.SendS2C(this.playerUuid, this.beingRevived));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RequestC2S extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
|
|
||||||
public RequestC2S(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestC2S(UUID playerUuid) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
if (knockableDown != null) {
|
|
||||||
KnockdownsNetwork.sendToPlayer(context.getPlayer(), new ReviveStatusPacket.SendS2C(this.playerUuid, knockableDown.knockdowns$isBeingRevived()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RevivedC2S extends KnockdownsPacket {
|
|
||||||
private final UUID playerUuid;
|
|
||||||
|
|
||||||
public RevivedC2S(PacketByteBuf buf) {
|
|
||||||
this(buf.readUuid());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RevivedC2S(UUID playerUuid) {
|
|
||||||
this.playerUuid = playerUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(PacketByteBuf buf) {
|
|
||||||
buf.writeUuid(this.playerUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
|
||||||
NetworkManager.PacketContext context = contextSupplier.get();
|
|
||||||
context.queue(() -> {
|
|
||||||
PlayerEntity reviving = context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
|
|
||||||
IKnockableDown knockableDown = (IKnockableDown) reviving;
|
|
||||||
if (knockableDown == null || !knockableDown.knockdowns$isKnockedDown()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reviving.setInvulnerable(false);
|
|
||||||
reviving.setGlowing(false);
|
|
||||||
reviving.setHealth(6.0f);
|
|
||||||
|
|
||||||
knockableDown.knockdowns$setKnockedDown(false);
|
|
||||||
KnockdownsNetwork.sendToListenersAndSelf(reviving, new KnockedDownStatusPacket.SendS2C(reviving.getUuid(), false));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets;
|
||||||
|
|
||||||
|
import dev.architectury.networking.NetworkManager;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
|
||||||
|
|
||||||
|
public class StopRevivingC2SPacket extends KnockdownsPacket {
|
||||||
|
private final UUID targetUuid;
|
||||||
|
|
||||||
|
public StopRevivingC2SPacket(PacketByteBuf buf) {
|
||||||
|
this(buf.readUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public StopRevivingC2SPacket(UUID targetUuid) {
|
||||||
|
this.targetUuid = targetUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(PacketByteBuf buf) {
|
||||||
|
buf.writeUuid(this.targetUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
|
||||||
|
NetworkManager.PacketContext context = contextSupplier.get();
|
||||||
|
context.queue(() -> {
|
||||||
|
PlayerEntity player = context.getPlayer();
|
||||||
|
IKnockableDown playerKnockable = (IKnockableDown) player;
|
||||||
|
IKnockableDown targetKnockable = (IKnockableDown) player.getWorld().getPlayerByUuid(this.targetUuid);
|
||||||
|
if (playerKnockable.is_Reviving() && targetKnockable != null) {
|
||||||
|
playerKnockable.set_Reviving(false);
|
||||||
|
if (targetKnockable.is_KnockedDown()) {
|
||||||
|
targetKnockable.set_ReviverCount(targetKnockable.get_ReviverCount() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"subtitles.knockdowns.knocked_down": "Player knocked down",
|
||||||
|
|
||||||
"knockdown.attack.anvil": "%1$s was knocked down by a falling anvil",
|
"knockdown.attack.anvil": "%1$s was knocked down by a falling anvil",
|
||||||
"knockdown.attack.anvil.player": "%1$s was knocked down by a falling anvil while fighting %2$s",
|
"knockdown.attack.anvil.player": "%1$s was knocked down by a falling anvil while fighting %2$s",
|
||||||
"knockdown.attack.arrow": "%1$s was knocked down due to an arrow fired by %2$s",
|
"knockdown.attack.arrow": "%1$s was knocked down due to an arrow fired by %2$s",
|
||||||
|
@ -97,6 +99,5 @@
|
||||||
"knockdown.fell.assist.item": "%1$s was doomed to get knocked down by %2$s using %3$s",
|
"knockdown.fell.assist.item": "%1$s was doomed to get knocked down by %2$s using %3$s",
|
||||||
"knockdown.fell.finish": "%1$s fell too far and was knocked down by %2$s",
|
"knockdown.fell.finish": "%1$s fell too far and was knocked down by %2$s",
|
||||||
"knockdown.fell.finish.item": "%1$s fell too far and was knocked down by %2$s using %3$s",
|
"knockdown.fell.finish.item": "%1$s fell too far and was knocked down by %2$s using %3$s",
|
||||||
"knockdown.fell.killer": "%1$s was doomed to get knocked down by a fall",
|
"knockdown.fell.killer": "%1$s was doomed to get knocked down by a fall"
|
||||||
"subtitles.knockdowns.knocked_down": "Player knocked down"
|
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"subtitles.knockdowns.knocked_down": "Игрок тяжело ранен",
|
||||||
|
|
||||||
"knockdown.attack.anvil": "%1$s был тяжело ранен упавшей наковальней",
|
"knockdown.attack.anvil": "%1$s был тяжело ранен упавшей наковальней",
|
||||||
"knockdown.attack.anvil.player": "%1$s был тяжело ранен упавшей наковальней, пока сражался с %2$s",
|
"knockdown.attack.anvil.player": "%1$s был тяжело ранен упавшей наковальней, пока сражался с %2$s",
|
||||||
"knockdown.attack.arrow": "%1$s тяжело ранен стрелой %2$s",
|
"knockdown.attack.arrow": "%1$s тяжело ранен стрелой %2$s",
|
||||||
|
@ -97,6 +99,5 @@
|
||||||
"knockdown.fell.assist.item": "%1$s был тяжело ранен падением благодаря %2$s с помощью %3$s",
|
"knockdown.fell.assist.item": "%1$s был тяжело ранен падением благодаря %2$s с помощью %3$s",
|
||||||
"knockdown.fell.finish": "%1$s упал с высоты и был тяжело ранен %2$s",
|
"knockdown.fell.finish": "%1$s упал с высоты и был тяжело ранен %2$s",
|
||||||
"knockdown.fell.finish.item": "%1$s упал с высоты и был тяжело ранен %2$s с помощью %3$s",
|
"knockdown.fell.finish.item": "%1$s упал с высоты и был тяжело ранен %2$s с помощью %3$s",
|
||||||
"knockdown.fell.killer": "%1$s был тяжело ранен падением",
|
"knockdown.fell.killer": "%1$s был тяжело ранен падением"
|
||||||
"subtitles.knockdowns.knocked_down": "Игрок тяжело ранен"
|
|
||||||
}
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
"client.ClientPlayerEntityMixin"
|
"client.ClientPlayerEntityMixin"
|
||||||
],
|
],
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"LivingEntityMixin",
|
||||||
|
"MobEntityMixin",
|
||||||
"PlayerEntityMixin"
|
"PlayerEntityMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
|
|
|
@ -1,4 +1 @@
|
||||||
accessWidener v2 named
|
accessWidener v2 named
|
||||||
|
|
||||||
accessible field net/minecraft/server/world/ThreadedAnvilChunkStorage entityTrackers Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;
|
|
||||||
accessible field net/minecraft/server/world/ThreadedAnvilChunkStorage$EntityTracker listeners Ljava/util/Set;
|
|
Loading…
Reference in a new issue