Skip to content

Commit

Permalink
Add optional auto reviving
Browse files Browse the repository at this point in the history
With a gamerule to enable it!
  • Loading branch information
QPCrummer committed Jan 6, 2025
1 parent 85e5d26 commit 08add01
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ hs_err_pid*
.gradle/
build/
/run/
.qodo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.loader.api.FabricLoader;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.certifiedtater.lifesteal.commands;

import com.github.certifiedtater.lifesteal.data.DeathData;
import com.github.certifiedtater.lifesteal.gamerules.LifeStealGamerules;
import com.github.certifiedtater.lifesteal.items.HeartItem;
import com.github.certifiedtater.lifesteal.utils.LifeStealText;
import com.mojang.authlib.GameProfile;
Expand Down Expand Up @@ -36,7 +37,7 @@ public static int reset(CommandContext<ServerCommandSource> context) throws Comm
return 0;
}
final GameProfile receiver = profiles.iterator().next();
if (!DeathData.isPlayerDead(receiver.getId())) {
if (!DeathData.isPlayerDead(receiver.getId(), source.getServer().getGameRules().getInt(LifeStealGamerules.AUTOREVIVAL))) {
// Error
source.sendError(LifeStealText.playerIsAlive(Text.of(receiver.getName())));
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static int gift(CommandContext<ServerCommandSource> context) throws Comma
return 0;
}

if (DeathData.isPlayerDead(receiver.getId())) {
if (DeathData.isPlayerDead(receiver.getId(), gameRules.getInt(LifeStealGamerules.AUTOREVIVAL))) {
// Can't gift to a dead guy
source.sendError(LifeStealText.isDead(Text.of(receiver.getName())));
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
public class DeathData {
public final UUID deadPlayerID;
public UUID reviverPlayerID;
public final long deathTime;

public DeathData(UUID deadPlayerID) {
this.deadPlayerID = deadPlayerID;
this.deathTime = System.currentTimeMillis() / 1000;
}

public DeathData(UUID deadPlayerID, UUID reviverPlayerID) {
this.deadPlayerID = deadPlayerID;
this.reviverPlayerID = reviverPlayerID;
this.deathTime = System.currentTimeMillis() / 1000;
}

public void addToDeathDataList() {
Expand Down Expand Up @@ -74,12 +77,26 @@ public static void loadDeathDataFromFile() {
}
}

public static boolean isPlayerDead(UUID player) {
public static boolean isPlayerDead(UUID player, int waitTime) {
DeathData data = Lifesteal.DEAD_PLAYERS.get(player);
if (data != null) {
if (shouldAutoRevive(data, waitTime)) {
// Revive
removeFromDeathDataList(player);
return false;
}

return data.reviverPlayerID == null;
} else {
return false;
}
}

public static boolean shouldAutoRevive(DeathData data, int waitTime) {
if (waitTime == 0) {
return false;
}

return waitTime <= (System.currentTimeMillis() * 0.001) - data.deathTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public static void init() {
createRegistryEntryRule(Registries.BLOCK, Blocks.NETHERITE_BLOCK,
(server, blockRegistryEntryRule) -> altarGameRuleModified = true));

/**
* The amount of seconds until the player is automatically revived
* Setting this to 0 will disable auto-revival
*/
public static final GameRules.Key<GameRules.IntRule> AUTOREVIVAL = GameRuleRegistry.register(Lifesteal.MOD_ID + ":autoRevivalSeconds", GameRules.Category.PLAYER, GameRuleFactory.createIntRule(0, 0));

public static boolean altarGameRuleModified = true;
private static Block cachedAltarBlock;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public static int revive(String playerName, MinecraftServer server, ServerWorld
}

private static boolean reviveOnline(ServerPlayerEntity player, ServerWorld world, BlockPos alter, PlayerEntity reviver) {
if (!DeathData.isPlayerDead(player.getUuid())) {
if (!DeathData.isPlayerDead(player.getUuid(), world.getGameRules().getInt(LifeStealGamerules.AUTOREVIVAL))) {
return false;
}
teleport(player, world, alter);
Expand All @@ -147,7 +147,7 @@ private static boolean reviveOnline(ServerPlayerEntity player, ServerWorld world
}

private static boolean reviveOffline(GameProfile profile, ServerWorld world, BlockPos alter, PlayerEntity reviver) {
if (!DeathData.isPlayerDead(profile.getId())) {
if (!DeathData.isPlayerDead(profile.getId(), world.getGameRules().getInt(LifeStealGamerules.AUTOREVIVAL))) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.certifiedtater.lifesteal.mixin;

import com.github.certifiedtater.lifesteal.data.DeathData;
import com.github.certifiedtater.lifesteal.gamerules.LifeStealGamerules;
import com.github.certifiedtater.lifesteal.utils.PlayerUtils;
import com.mojang.authlib.GameProfile;
Expand Down Expand Up @@ -35,6 +36,14 @@ private void onDeath(DamageSource damageSource, CallbackInfo ci) {
} else if (!getServerWorld().getGameRules().getBoolean(LifeStealGamerules.PLAYERRELATEDONLY)) {
EntityAttributeInstance killedMaxHealth = this.getAttributeInstance(EntityAttributes.MAX_HEALTH);
PlayerUtils.changeHealth(((ServerPlayerEntity) (Object) this), killedMaxHealth, -getServerWorld().getGameRules().getInt(LifeStealGamerules.STEALAMOUNT));
// Check to see if the player is dead
int minHealth = this.getServer().getGameRules().getInt(LifeStealGamerules.MINPLAYERHEALTH);
if (killedMaxHealth.getBaseValue() <= minHealth) {
// Considered dead
DeathData data = new DeathData(this.getUuid());
data.addToDeathDataList();
PlayerUtils.handleDeadPlayerAction((ServerPlayerEntity)(Object)this, data);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public final class LifeStealText {
REVIVEE = "lifesteal.player.revived.receiver",
REVIVER = "lifesteal.player.revived.sender",
SELF_REVIVE = "lifesteal.revive.self",
DEATH_TIME = "lifesteal.gameplay.death_time",
ADMIN_REVIVE = "lifesteal.admin.revive";

public static Text onRevivalText(DeathData data, MinecraftServer server) {
Expand Down Expand Up @@ -98,4 +99,8 @@ public static Text updateHealth(double changeAmount) { // +X Health
public static Text adminRevive(String player) {
return Text.translatable(ADMIN_REVIVE, player);
}

public static Text deathTime(int seconds) {
return Text.translatable(DEATH_TIME, seconds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void exchangeHealth(ServerPlayerEntity killed, ServerPlayerEntity
// Considered dead
DeathData data = new DeathData(killed.getUuid());
data.addToDeathDataList();
handleDeadPlayerAction(killed);
handleDeadPlayerAction(killed, data);

// Check to see if spawn camping is happening
if (killedMaxHealthDouble < minHealth && gameRules.getBoolean(LifeStealGamerules.ANTIHEARTDUPE)) {
Expand Down Expand Up @@ -66,11 +66,17 @@ public static boolean canChangeHealth(double currentMaxHealth, float by, GameRul
return newMaxHealth >= gameRules.getInt(LifeStealGamerules.MINPLAYERHEALTH) && newMaxHealth <= gameRules.getInt(LifeStealGamerules.MAXPLAYERHEALTH);
}

public static void handleDeadPlayerAction(ServerPlayerEntity player) {
public static void handleDeadPlayerAction(ServerPlayerEntity player, DeathData data) {
GameRules gameRules = player.getServerWorld().getGameRules();
DeathAction action = gameRules.get(LifeStealGamerules.DEATH_ACTION).get();
switch (action) {
case BAN -> player.networkHandler.disconnect(LifeStealText.DEATH);
case BAN -> {
if (gameRules.get(LifeStealGamerules.AUTOREVIVAL).get() == 0) {
player.networkHandler.disconnect(LifeStealText.DEATH);
} else {
player.networkHandler.disconnect(LifeStealText.deathTime((int) (data.deathTime + gameRules.get(LifeStealGamerules.AUTOREVIVAL).get() - (System.currentTimeMillis() * 0.001))));
}
}
case REVIVE -> {
setMaxHealth(gameRules.getInt(LifeStealGamerules.MINPLAYERHEALTH) - 0.01, player); // It's basically Min Health... Right?
DeathData.removeFromDeathDataList(player.getUuid()); // I know this is a waste of processing power... but I don't care
Expand All @@ -82,18 +88,26 @@ public static void handleDeadPlayerAction(ServerPlayerEntity player) {
public static void handlePlayerJoin(ServerPlayerEntity player) {
DeathData data = Lifesteal.DEAD_PLAYERS.get(player.getUuid());
if (data != null) {
// Check and see if they can be revived
if (DeathData.shouldAutoRevive(data, player.getServerWorld().getGameRules().getInt(LifeStealGamerules.AUTOREVIVAL))) {
handlePostRevival(data, player, true);
return;
}
// Else do traditional checks
if (data.reviverPlayerID == null) {
handleDeadPlayerAction(player);
handleDeadPlayerAction(player, data);
} else {
handlePostRevival(data, player);
handlePostRevival(data, player, false);
}
}
}

public static void handlePostRevival(DeathData data, ServerPlayerEntity player) {
public static void handlePostRevival(DeathData data, ServerPlayerEntity player, boolean autoRevived) {
GameRules gameRules = player.getServerWorld().getGameRules();
setMaxHealth(gameRules.getInt(LifeStealGamerules.MINPLAYERHEALTH), player);
player.sendMessage(LifeStealText.onRevivalText(data, player.server));
if (!autoRevived) {
player.sendMessage(LifeStealText.onRevivalText(data, player.server));
}
DeathData.removeFromDeathDataList(player.getUuid());
}

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/data/lifesteal/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"lifesteal.failure.unknown": "Unknown fault. If you're the server admin, check logs.",

"lifesteal.gameplay.death": "You lost your last life. You now must be revived.",
"lifesteal.gameplay.death_time": "You lost your last life.\nYou will be revived in %s seconds.",
"lifesteal.gameplay.low_health": "You have insufficient health for this task.",
"lifesteal.gameplay.max_health": "You are already at the maximum amount of health",
"lifesteal.gameplay.update_health": "%s Health",
Expand Down

0 comments on commit 08add01

Please sign in to comment.