aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/world
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/world')
-rw-r--r--src/main/java/world/anhgelus/lifesteal/LifeStealer.java98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/main/java/world/anhgelus/lifesteal/LifeStealer.java b/src/main/java/world/anhgelus/lifesteal/LifeStealer.java
new file mode 100644
index 0000000..86410de
--- /dev/null
+++ b/src/main/java/world/anhgelus/lifesteal/LifeStealer.java
@@ -0,0 +1,98 @@
+package world.anhgelus.lifesteal;
+
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.component.type.NbtComponent;
+import net.minecraft.entity.attribute.EntityAttributeModifier;
+import net.minecraft.entity.attribute.EntityAttributes;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.server.network.ServerPlayerEntity;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.math.MathHelper;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class LifeStealer {
+ public static final Identifier HEALTH_MODIFIER = Identifier.of(LifeSteal.MOD_ID, "health_modifier");
+ public static final String PLAYER_KEY = "player";
+
+ private ServerPlayerEntity player;
+ private final UUID uuid;
+ private float healthModifier;
+
+ public LifeStealer(ServerPlayerEntity player, Data data) {
+ this.player = player;
+ this.uuid = player.getUuid();
+ this.healthModifier = data.healthModifier();
+ }
+
+ private void updateHealth() {
+ healthModifier = MathHelper.clamp(healthModifier, -20, 20);
+ final var attr = player.getAttributeInstance(EntityAttributes.MAX_HEALTH);
+ if (attr == null) throw new IllegalStateException("No health attribute assigned to LifeStealer");
+ if (attr.hasModifier(HEALTH_MODIFIER)) attr.removeModifier(HEALTH_MODIFIER);
+ final var modifier = new EntityAttributeModifier(HEALTH_MODIFIER, healthModifier, EntityAttributeModifier.Operation.ADD_VALUE);
+ attr.addTemporaryModifier(modifier);
+ }
+
+ public ItemStack getHeart() {
+ final var nbt = new NbtCompound();
+ nbt.putString(PLAYER_KEY, player.getUuid().toString());
+ final var is = new ItemStack(Items.NETHER_STAR);
+ is.set(DataComponentTypes.CUSTOM_NAME, player.getName());
+ is.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(nbt));
+ return is;
+ }
+
+ public void respawn(ServerPlayerEntity newPlayer) {
+ if (!newPlayer.getUuid().equals(uuid)) throw new IllegalArgumentException("Player does not have the same UUID");
+ this.player = newPlayer;
+ updateHealth();
+ }
+
+ public void kill() {
+ healthModifier = MathHelper.clamp(healthModifier + 2, -20, 20);
+ updateHealth();
+ }
+
+ public void killed() {
+ healthModifier = MathHelper.clamp(healthModifier - 2, -20, 20);
+ if (healthModifier <= 0) {
+ //TODO: ban player
+ return;
+ }
+ updateHealth();
+ }
+
+ public float getHealthModifier() {
+ return healthModifier;
+ }
+
+ public record Data(float healthModifier) {
+ public final static String HEALTH_MODIFIER_KEY = "health_modifier";
+ public static final Codec<Data> CODEC = RecordCodecBuilder.create(i -> i.group(
+ Codec.FLOAT.fieldOf(HEALTH_MODIFIER_KEY).forGetter(Data::healthModifier)
+ ).apply(i, Data::new));
+
+ public static Data DEFAULT = new Data(0.0F);
+ }
+
+ public static class Manager {
+ private static final Map<UUID, LifeStealer> players = new HashMap<>();
+
+ public static LifeStealer getLifeStealer(ServerPlayerEntity player) {
+ return players.computeIfAbsent(player.getUuid(), k -> new LifeStealer(player, Data.DEFAULT));
+ }
+
+ @Nullable
+ public static LifeStealer getLifeStealer(UUID uuid) {
+ return players.get(uuid);
+ }
+ }
+}