Fix player tick logic to track timing per player, optimize stat sync, and clean up unused code
This commit is contained in:
@@ -72,3 +72,12 @@ This changelog covers all recorded changes after `1.0.0`, grouped by release ver
|
|||||||
- Simplified and retuned parts of the stat effect implementation, including melee and magic scaling behavior.
|
- Simplified and retuned parts of the stat effect implementation, including melee and magic scaling behavior.
|
||||||
- Fixed the stats screen so custom configured max Ascend levels display correctly instead of staying at `20/20`.
|
- Fixed the stats screen so custom configured max Ascend levels display correctly instead of staying at `20/20`.
|
||||||
- Synced max Ascend and attribute caps through player stat data so the client GUI respects the server-authoritative config.
|
- Synced max Ascend and attribute caps through player stat data so the client GUI respects the server-authoritative config.
|
||||||
|
|
||||||
|
## 2.2.3
|
||||||
|
|
||||||
|
- Fixed death respawns so players with fortitude bonus health respawn at their full modified maximum health instead of the vanilla 10 hearts.
|
||||||
|
- Fixed stat resets and refunds so removed bonuses immediately clamp current health back down to the recalculated maximum.
|
||||||
|
- Fixed player tick progression logic so fortitude, agility, willpower, and charisma timing is tracked per player instead of through shared server-wide counters.
|
||||||
|
- Hardened player stat synchronization against accidental non-server-player calls.
|
||||||
|
- Fixed player clone capability cleanup after copying Ascend stats to the respawned player.
|
||||||
|
- Removed an unused attack-speed lookup from weapon XP handling.
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ mod_name=Ascend: SbA
|
|||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=All Rights Reserved
|
mod_license=All Rights Reserved
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=2.2.2
|
mod_version=2.2.3
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import net.minecraft.core.particles.ParticleTypes;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.world.effect.MobEffectCategory;
|
import net.minecraft.world.effect.MobEffectCategory;
|
||||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
||||||
import net.minecraft.world.entity.ai.gossip.GossipType;
|
import net.minecraft.world.entity.ai.gossip.GossipType;
|
||||||
import net.minecraft.world.entity.npc.Villager;
|
import net.minecraft.world.entity.npc.Villager;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
@@ -32,17 +31,11 @@ import net.minecraft.world.entity.animal.SnowGolem;
|
|||||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
import net.minecraftforge.event.entity.living.LivingEvent;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
|
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
|
||||||
public class ActivityEvents {
|
public class ActivityEvents {
|
||||||
|
|
||||||
private static int agilityTickCounter = 0;
|
|
||||||
private static int fortitudeTickCounter = 0;
|
|
||||||
private static int willpowerTickCounter = 0;
|
|
||||||
private static int charismaTickCounter = 0;
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onMobKilled(LivingDeathEvent event) {
|
public static void onMobKilled(LivingDeathEvent event) {
|
||||||
if (event.getSource().getEntity() instanceof Player player && !player.level().isClientSide) {
|
if (event.getSource().getEntity() instanceof Player player && !player.level().isClientSide) {
|
||||||
@@ -86,8 +79,7 @@ public class ActivityEvents {
|
|||||||
public static void onPlayerTickFortitude(TickEvent.PlayerTickEvent event) {
|
public static void onPlayerTickFortitude(TickEvent.PlayerTickEvent event) {
|
||||||
Player player = event.player;
|
Player player = event.player;
|
||||||
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
||||||
fortitudeTickCounter++;
|
if (player.tickCount % 100 != 0) return;
|
||||||
if (fortitudeTickCounter % 100 == 0) {
|
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
boolean hasNegativeEffect = player.getActiveEffects().stream()
|
boolean hasNegativeEffect = player.getActiveEffects().stream()
|
||||||
.anyMatch(e -> e.getEffect().getCategory() == MobEffectCategory.HARMFUL);
|
.anyMatch(e -> e.getEffect().getCategory() == MobEffectCategory.HARMFUL);
|
||||||
@@ -97,14 +89,12 @@ public class ActivityEvents {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerTickAgility(TickEvent.PlayerTickEvent event) {
|
public static void onPlayerTickAgility(TickEvent.PlayerTickEvent event) {
|
||||||
Player player = event.player;
|
Player player = event.player;
|
||||||
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
||||||
agilityTickCounter++;
|
if (player.tickCount % 40 != 0) return;
|
||||||
if (agilityTickCounter % 40 != 0) return;
|
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
boolean didAgileThing =
|
boolean didAgileThing =
|
||||||
player.isSprinting()
|
player.isSprinting()
|
||||||
@@ -142,16 +132,15 @@ public class ActivityEvents {
|
|||||||
public static void onPlayerTickWillpower(TickEvent.PlayerTickEvent event) {
|
public static void onPlayerTickWillpower(TickEvent.PlayerTickEvent event) {
|
||||||
Player player = event.player;
|
Player player = event.player;
|
||||||
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
||||||
willpowerTickCounter++;
|
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
int willpower = stats.getAttributeLevel("willpower");
|
int willpower = stats.getAttributeLevel("willpower");
|
||||||
if (willpower > 0 && willpowerTickCounter % 80 == 0) {
|
if (willpower > 0 && player.tickCount % 80 == 0) {
|
||||||
float regen = StatEffects.getWillpowerHealthRegen(willpower);
|
float regen = StatEffects.getWillpowerHealthRegen(willpower);
|
||||||
if (regen > 0.0f && player.getHealth() < player.getMaxHealth()) {
|
if (regen > 0.0f && player.getHealth() < player.getMaxHealth()) {
|
||||||
player.heal(regen);
|
player.heal(regen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (willpowerTickCounter % 200 != 0) return;
|
if (player.tickCount % 200 != 0) return;
|
||||||
boolean hasNegativeEffect = player.getActiveEffects().stream()
|
boolean hasNegativeEffect = player.getActiveEffects().stream()
|
||||||
.anyMatch(e -> e.getEffect().getCategory() == MobEffectCategory.HARMFUL);
|
.anyMatch(e -> e.getEffect().getCategory() == MobEffectCategory.HARMFUL);
|
||||||
boolean lowHealth = player.getHealth() <= player.getMaxHealth() * 0.25f;
|
boolean lowHealth = player.getHealth() <= player.getMaxHealth() * 0.25f;
|
||||||
@@ -171,8 +160,7 @@ public class ActivityEvents {
|
|||||||
public static void onPlayerTickCharisma(TickEvent.PlayerTickEvent event) {
|
public static void onPlayerTickCharisma(TickEvent.PlayerTickEvent event) {
|
||||||
Player player = event.player;
|
Player player = event.player;
|
||||||
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
|
||||||
charismaTickCounter++;
|
if (player.tickCount % 40 != 0) return;
|
||||||
if (charismaTickCounter % 40 != 0) return;
|
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
int charisma = stats.getAttributeLevel("charisma");
|
int charisma = stats.getAttributeLevel("charisma");
|
||||||
if (charisma <= 0) return;
|
if (charisma <= 0) return;
|
||||||
@@ -222,9 +210,6 @@ public class ActivityEvents {
|
|||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
var heldItem = player.getMainHandItem();
|
var heldItem = player.getMainHandItem();
|
||||||
if (heldItem.isEmpty()) return;
|
if (heldItem.isEmpty()) return;
|
||||||
double attackSpeed = Objects.requireNonNull(player.getAttribute(
|
|
||||||
Attributes.ATTACK_SPEED
|
|
||||||
)).getBaseValue();
|
|
||||||
stats.addAscendXP(3);
|
stats.addAscendXP(3);
|
||||||
PlayerStatsProvider.sync(player);
|
PlayerStatsProvider.sync(player);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class PlayerEvents {
|
|||||||
newStats.deserializeNBT(oldStats.serializeNBT());
|
newStats.deserializeNBT(oldStats.serializeNBT());
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
event.getOriginal().invalidateCaps();
|
||||||
if (!event.getEntity().level().isClientSide) {
|
if (!event.getEntity().level().isClientSide) {
|
||||||
StatEffects.applyAll(event.getEntity());
|
StatEffects.applyAll(event.getEntity());
|
||||||
if (event.isWasDeath()) {
|
if (event.isWasDeath()) {
|
||||||
|
|||||||
@@ -39,9 +39,12 @@ public class PlayerStatsProvider implements ICapabilitySerializable<CompoundTag>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void sync(Player player) {
|
public static void sync(Player player) {
|
||||||
|
if (!(player instanceof ServerPlayer serverPlayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
CompoundTag data = stats.serializeNBT();
|
CompoundTag data = stats.serializeNBT();
|
||||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player),
|
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> serverPlayer),
|
||||||
new ClientboundSyncStatsPacket(data));
|
new ClientboundSyncStatsPacket(data));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user