diff options
| author | William Hergès <william@herges.fr> | 2025-10-12 17:02:48 +0200 |
|---|---|---|
| committer | William Hergès <william@herges.fr> | 2025-10-12 17:02:48 +0200 |
| commit | cb9b24a15cbcd3e534dcc7939b3c566ab0204436 (patch) | |
| tree | 0bcae2e6ca5ebde32e895624c761a3b76bf7b4c7 | |
| parent | 3307cef52177c882bdc9f956b2dd72fbb9e9753f (diff) | |
feat(player): represents custom data
| -rwxr-xr-x[-rw-r--r--] | LICENSE (renamed from LICENSE.txt) | 55 | ||||
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | src/main/java/world/anhgelus/lifesteal/LifeStealer.java | 98 |
3 files changed, 143 insertions, 13 deletions
diff --git a/LICENSE.txt b/LICENSE index 313e689..9718cb2 100644..100755 --- a/LICENSE.txt +++ b/LICENSE @@ -1,19 +1,7 @@ -Copyright (c) 2025 - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -629,3 +617,44 @@ Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + LifeSteal Copyright (C) <no value> William Hergès + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<https://www.gnu.org/licenses/>. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2f233a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# LifeSteal + +LifeSteal is a server-side mod recreating the LifeSteal SMP experience. 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); + } + } +} |
