Increase invulnerability period and tenacity periods

This commit is contained in:
Octol1ttle 2024-02-16 17:13:30 +05:00
parent cc20e19a4b
commit 34ea071e5f
Signed by: Octol1ttle
GPG key ID: B77C34313AEE1FFF
7 changed files with 86 additions and 29 deletions

View file

@ -31,7 +31,7 @@ public class KnockdownsClient {
} }
public static EventResult onEntityUse(PlayerEntity player, Entity entity) { public static EventResult onEntityUse(PlayerEntity player, Entity entity) {
if (KnockdownsCommon.isKnockedOrReviving(player) || !(entity instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) { if (KnockdownsUtils.isKnockedOrReviving(player) || !(entity instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) {
return EventResult.pass(); return EventResult.pass();
} }
@ -49,7 +49,7 @@ public class KnockdownsClient {
boolean playerKnocked = ((IKnockableDown) player).is_KnockedDown(); boolean playerKnocked = ((IKnockableDown) player).is_KnockedDown();
boolean revivingTargeted = client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.ENTITY boolean revivingTargeted = client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.ENTITY
&& ((EntityHitResult) client.crosshairTarget).getEntity().getUuid().equals(reviving.getUuid()); && ((EntityHitResult) client.crosshairTarget).getEntity().equals(reviving);
if (!(reviving instanceof IKnockableDown knockable)) { if (!(reviving instanceof IKnockableDown knockable)) {
return; return;

View file

@ -1,8 +1,6 @@
package ru.octol1ttle.knockdowns.common; package ru.octol1ttle.knockdowns.common;
import net.minecraft.SharedConstants; 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;
@ -16,8 +14,4 @@ public class KnockdownsCommon {
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());
}
} }

View file

@ -0,0 +1,31 @@
package ru.octol1ttle.knockdowns.common;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
public class KnockdownsUtils {
public static boolean isKnockedOrReviving(PlayerEntity player) {
return player instanceof IKnockableDown knockable && (knockable.is_KnockedDown() || knockable.is_Reviving());
}
public static boolean allTeammatesKnocked(MinecraftServer server, PlayerEntity player) {
for (PlayerEntity teammate : server.getPlayerManager().getPlayerList()) {
if (teammate.equals(player)) {
continue;
}
IKnockableDown knockable = (IKnockableDown) teammate;
if (!knockable.is_KnockedDown() && !player.isDead()) {
return false;
}
}
return true;
}
public static void hurtTenacity(PlayerEntity player, float damage) {
player.setInvulnerable(false);
//DamageSource recent = player.getRecentDamageSource();
player.damage(/*Objects.requireNonNullElse(recent, */player.getDamageSources().generic()/*)*/, damage);
player.velocityModified = false;
}
}

View file

@ -16,4 +16,8 @@ public interface IKnockableDown {
int get_ReviveTimer(); int get_ReviveTimer();
void set_ReviveTimer(int reviveTimer); void set_ReviveTimer(int reviveTimer);
int get_KnockedAge();
void set_KnockedAge(int knockedAge);
} }

View file

@ -6,21 +6,24 @@ 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 dev.architectury.event.events.common.TickEvent;
import java.util.Objects; import net.minecraft.SharedConstants;
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.util.math.MathHelper;
import ru.octol1ttle.knockdowns.common.KnockdownsClient; import ru.octol1ttle.knockdowns.common.KnockdownsClient;
import ru.octol1ttle.knockdowns.common.KnockdownsCommon; import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
import ru.octol1ttle.knockdowns.common.KnockdownsUtils;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown; import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork; 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; private static final float KNOCKED_INVULNERABILITY_TICKS = 3.0f * SharedConstants.TICKS_PER_SECOND;
private static final float KNOCKED_HURT_PERIOD = 1.2f;
private static final float KNOCKED_TENACITY = 60.0f;
public static void registerCallbacks() { public static void registerCallbacks() {
registerOnLivingDeath(); registerOnLivingDeath();
@ -31,13 +34,14 @@ public class KnockdownsEvents {
private static void registerOnLivingDeath() { private static void registerOnLivingDeath() {
EntityEvent.LIVING_DEATH.register((entity, source) -> { EntityEvent.LIVING_DEATH.register((entity, source) -> {
if (entity.getWorld().isClient() || !(entity instanceof IKnockableDown knockable)) { MinecraftServer server = entity.getServer();
if (server == null || !(entity instanceof IKnockableDown knockable)) {
return EventResult.pass(); return EventResult.pass();
} }
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) entity; ServerPlayerEntity player = (ServerPlayerEntity) entity;
MinecraftServer server = serverPlayer.getServer();
if (server == null || server.getCurrentPlayerCount() == 1) { if (KnockdownsUtils.allTeammatesKnocked(server, player)) {
return EventResult.pass(); return EventResult.pass();
} }
@ -45,6 +49,7 @@ public class KnockdownsEvents {
knockable.set_KnockedDown(false); knockable.set_KnockedDown(false);
knockable.set_ReviverCount(0); knockable.set_ReviverCount(0);
knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME); knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME);
knockable.set_KnockedAge(0);
return EventResult.pass(); return EventResult.pass();
} }
@ -56,12 +61,13 @@ public class KnockdownsEvents {
entity.extinguish(); entity.extinguish();
entity.setAir(entity.getMaxAir()); entity.setAir(entity.getMaxAir());
entity.setFrozenTicks(0); entity.setFrozenTicks(0);
serverPlayer.stopFallFlying(); player.stopFallFlying();
knockable.set_KnockedDown(true); knockable.set_KnockedDown(true);
knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME); knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME);
knockable.set_KnockedAge(0);
KnockdownsNetwork.sendToWorld(serverPlayer.getServerWorld(), new PlayKnockedDownSoundS2CPacket(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ())); KnockdownsNetwork.sendToWorld(player.getServerWorld(), new PlayKnockedDownSoundS2CPacket(player.getX(), player.getY(), player.getZ()));
Text deathMessage = entity.getDamageTracker().getDeathMessage(); Text deathMessage = entity.getDamageTracker().getDeathMessage();
TranslatableTextContent content = (TranslatableTextContent) deathMessage.getContent(); TranslatableTextContent content = (TranslatableTextContent) deathMessage.getContent();
@ -75,13 +81,20 @@ public class KnockdownsEvents {
private static void registerOnPlayerTick() { private static void registerOnPlayerTick() {
TickEvent.PLAYER_POST.register(player -> { TickEvent.PLAYER_POST.register(player -> {
if (player.getWorld().isClient()) { MinecraftServer server = player.getServer();
if (server == null) {
KnockdownsClient.onPlayerTick(player); KnockdownsClient.onPlayerTick(player);
return; return;
} }
if (!(player instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) { if (!(player instanceof IKnockableDown knockable) || !knockable.is_KnockedDown()) {
return; return;
} }
if (KnockdownsUtils.allTeammatesKnocked(server, player)) {
KnockdownsUtils.hurtTenacity(player, player.getMaxHealth());
return;
}
if (knockable.get_ReviverCount() > 0) { if (knockable.get_ReviverCount() > 0) {
knockable.set_ReviveTimer(knockable.get_ReviveTimer() - knockable.get_ReviverCount()); knockable.set_ReviveTimer(knockable.get_ReviveTimer() - knockable.get_ReviverCount());
@ -89,6 +102,7 @@ public class KnockdownsEvents {
knockable.set_KnockedDown(false); knockable.set_KnockedDown(false);
knockable.set_ReviverCount(0); knockable.set_ReviverCount(0);
knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME); knockable.set_ReviveTimer(KnockdownsCommon.REVIVE_WAIT_TIME);
knockable.set_KnockedAge(0);
player.setInvulnerable(false); player.setInvulnerable(false);
player.setGlowing(false); player.setGlowing(false);
@ -96,38 +110,38 @@ public class KnockdownsEvents {
} }
return; return;
} }
knockable.set_ReviveTimer(Math.min(KnockdownsCommon.REVIVE_WAIT_TIME, knockable.get_ReviveTimer() + 2)); knockable.set_ReviveTimer(Math.min(KnockdownsCommon.REVIVE_WAIT_TIME, knockable.get_ReviveTimer() + 1));
if (player.age % 20 == 0) { knockable.set_KnockedAge(knockable.get_KnockedAge() + 1);
player.setInvulnerable(false);
DamageSource recent = player.getRecentDamageSource(); int period = MathHelper.floor(KNOCKED_HURT_PERIOD * SharedConstants.TICKS_PER_SECOND);
player.damage(Objects.requireNonNullElse(recent, player.getDamageSources().generic()), player.getMaxHealth() / KNOCKED_DOWN_TIMER); if (knockable.get_KnockedAge() >= KNOCKED_INVULNERABILITY_TICKS && knockable.get_KnockedAge() % period == 0) {
player.velocityModified = false; KnockdownsUtils.hurtTenacity(player, player.getMaxHealth() / (KNOCKED_TENACITY / KNOCKED_HURT_PERIOD));
} }
}); });
} }
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 (KnockdownsCommon.isKnockedOrReviving(player)) { if (KnockdownsUtils.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 (KnockdownsCommon.isKnockedOrReviving(player)) { if (KnockdownsUtils.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 (KnockdownsCommon.isKnockedOrReviving(player)) { if (KnockdownsUtils.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 (KnockdownsCommon.isKnockedOrReviving(player)) { if (KnockdownsUtils.isKnockedOrReviving(player)) {
return EventResult.interruptFalse(); return EventResult.interruptFalse();
} }
return EventResult.pass(); return EventResult.pass();

View file

@ -30,6 +30,8 @@ public abstract class PlayerEntityMixin extends Entity implements IKnockableDown
private static final TrackedData<Integer> REVIVER_COUNT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER); private static final TrackedData<Integer> REVIVER_COUNT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
@Unique @Unique
private static final TrackedData<Integer> REVIVE_TIMER = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER); private static final TrackedData<Integer> REVIVE_TIMER = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
@Unique
public int knocked_age;
private PlayerEntityMixin(EntityType<?> type, World world) { private PlayerEntityMixin(EntityType<?> type, World world) {
super(type, world); super(type, world);
@ -65,12 +67,14 @@ public abstract class PlayerEntityMixin extends Entity implements IKnockableDown
private void readKnockedDownFromNbt(NbtCompound nbt, CallbackInfo ci) { private void readKnockedDownFromNbt(NbtCompound nbt, CallbackInfo ci) {
this.set_KnockedDown(nbt.getBoolean("KnockedDown")); this.set_KnockedDown(nbt.getBoolean("KnockedDown"));
this.set_ReviveTimer(nbt.getInt("ReviveTimer")); this.set_ReviveTimer(nbt.getInt("ReviveTimer"));
this.set_KnockedAge(nbt.getInt("KnockedAge"));
} }
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL")) @Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
private void writeKnockedDownToNbt(NbtCompound nbt, CallbackInfo ci) { private void writeKnockedDownToNbt(NbtCompound nbt, CallbackInfo ci) {
nbt.putBoolean("KnockedDown", this.is_KnockedDown()); nbt.putBoolean("KnockedDown", this.is_KnockedDown());
nbt.putInt("ReviveTimer", this.get_ReviveTimer()); nbt.putInt("ReviveTimer", this.get_ReviveTimer());
nbt.putInt("KnockedAge", this.get_KnockedAge());
} }
@Override @Override
@ -112,4 +116,14 @@ public abstract class PlayerEntityMixin extends Entity implements IKnockableDown
public void set_ReviveTimer(int reviveTimer) { public void set_ReviveTimer(int reviveTimer) {
this.dataTracker.set(REVIVE_TIMER, reviveTimer); this.dataTracker.set(REVIVE_TIMER, reviveTimer);
} }
@Override
public int get_KnockedAge() {
return knocked_age;
}
@Override
public void set_KnockedAge(int knockedAge) {
this.knocked_age = knockedAge;
}
} }

View file

@ -4,7 +4,7 @@ minecraft_version=1.20.1
enabled_platforms=fabric,forge enabled_platforms=fabric,forge
archives_base_name=knockdowns archives_base_name=knockdowns
mod_version=2.0.0 mod_version=2.1.0
maven_group=ru.octol1ttle.knockdowns maven_group=ru.octol1ttle.knockdowns
architectury_version=9.1.12 architectury_version=9.1.12