Skip to content

Commit

Permalink
feat: zombie-like traits
Browse files Browse the repository at this point in the history
style: rename TraitStates to ServerState
  • Loading branch information
Sigmarik committed Jun 26, 2023
1 parent 2964ec3 commit a912f74
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 24 deletions.
15 changes: 15 additions & 0 deletions src/main/java/net/sigmarik/abilitymod/AbilityMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.world.dimension.DimensionOptionsRegistryHolder;
import net.sigmarik.abilitymod.command.TraitCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -14,6 +15,20 @@ public class AbilityMod implements DedicatedServerModInitializer {
public static final String TRAIT_NO_EYE_AGGRO = "no_eye_aggro";
public static final String TRAIT_FEAR_OF_WATER = "fear_of_water";

public static final String TRAIT_IGNORED_BY_UNDEAD = "ignored_by_undead";
public static final String TRAIT_DAMAGED_BY_LIGHT = "damaged_by_light";
public static final String TRAIT_HARMFUL_ROTTEN_FLESH = "harmful_rotten_flesh";
public static final String TRAIT_INVERT_EFFECTS = "invert_effects";

public static final String TRAIT_BOAT_MAGNET = "boat_magnet";
public static final String TRAIT_CLEAN_COSTUME = "clean_costume";
public static final String TRAIT_QING = "qing";

public static final String TRAIT_FAST = "fast";
public static final String TRAIT_STRONG = "strong";
public static final String TRAIT_HATED = "hated";
public static final String TRAIT_HOT_IRON = "hot_iron";

@Override
public void onInitializeServer() {
LOGGER.info("Initializing AbilityMod.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.TraitStates;
import net.sigmarik.abilitymod.util.ServerState;

import java.util.Set;

Expand Down Expand Up @@ -39,7 +39,7 @@ private static int addTrait(CommandContext<ServerCommandSource> context) throws
java.util.Collection<net.minecraft.server.network.ServerPlayerEntity> players =
EntityArgumentType.getPlayers(context, "players");

TraitStates states = TraitStates.getTraitStates(context.getSource().getServer());
ServerState states = ServerState.getTraitStates(context.getSource().getServer());

for (ServerPlayerEntity player : players) {
AbilityMod.LOGGER.info("Adding trait " + trait + " to player " + player.getName().getString());
Expand All @@ -57,7 +57,7 @@ private static int removeTrait(CommandContext<ServerCommandSource> context) thro
java.util.Collection<net.minecraft.server.network.ServerPlayerEntity> players =
EntityArgumentType.getPlayers(context, "players");

TraitStates states = TraitStates.getTraitStates(context.getSource().getServer());
ServerState states = ServerState.getTraitStates(context.getSource().getServer());

for (ServerPlayerEntity player : players) {
AbilityMod.LOGGER.info("Removing trait " + trait + " from player " + player.getName().getString());
Expand All @@ -73,7 +73,7 @@ private static int removeTrait(CommandContext<ServerCommandSource> context) thro
private static int printTraits(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
ServerPlayerEntity player = EntityArgumentType.getPlayer(context, "player");

TraitStates states = TraitStates.getTraitStates(player.server);
ServerState states = ServerState.getTraitStates(player.server);
Set<String> traits = states.getTraitList(player.getUuid()).getKeys();

if (traits.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
import net.minecraft.entity.projectile.thrown.ThrownItemEntity;
import net.minecraft.world.World;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.TraitStates;
import net.sigmarik.abilitymod.util.ServerState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;

@Mixin(EnderPearlEntity.class)
public abstract class EnderPearlEntityMixin extends ThrownItemEntity {
Expand All @@ -25,7 +24,7 @@ public EnderPearlEntityMixin(EntityType<? extends ThrownItemEntity> entityType,
target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")
)
private boolean traitedDamage(Entity entity, DamageSource damageSource, float amount) {
if (TraitStates.hasTrait((PlayerEntity) entity, AbilityMod.TRAIT_EASY_PEARLS)) {
if (ServerState.hasTrait((PlayerEntity) entity, AbilityMod.TRAIT_EASY_PEARLS)) {
return false;
} else return entity.damage(damageSource, amount);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.sigmarik.abilitymod.mixin;

import net.minecraft.entity.player.ItemCooldownManager;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.EnderPearlItem;
import net.minecraft.item.Item;
Expand All @@ -10,12 +9,10 @@
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.TraitStates;
import net.sigmarik.abilitymod.util.ServerState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(EnderPearlItem.class)
Expand All @@ -31,7 +28,7 @@ public EnderPearlItemMixin(Settings settings) {
shift = At.Shift.AFTER
))
private void traiedSetDelay(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> cir) {
if (TraitStates.hasTrait(user, AbilityMod.TRAIT_EASY_PEARLS)) {
if (ServerState.hasTrait(user, AbilityMod.TRAIT_EASY_PEARLS)) {
user.getItemCooldownManager().set(Items.ENDER_PEARL, 0);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.TraitStates;
import net.sigmarik.abilitymod.util.ServerState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
Expand All @@ -22,6 +22,6 @@ protected EndermanEntityMixin(EntityType<? extends HostileEntity> entityType, Wo

@Inject(method = "isPlayerStaring", at = @At("HEAD"), cancellable = true)
private void traitedIsStaring(PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
if (TraitStates.hasTrait(player, AbilityMod.TRAIT_NO_EYE_AGGRO)) cir.setReturnValue(false);
if (ServerState.hasTrait(player, AbilityMod.TRAIT_NO_EYE_AGGRO)) cir.setReturnValue(false);
}
}
21 changes: 19 additions & 2 deletions src/main/java/net/sigmarik/abilitymod/mixin/PlayerEntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.TraitStates;
import net.sigmarik.abilitymod.util.ServerState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin extends LivingEntity {
Expand All @@ -20,8 +25,20 @@ protected PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World

@Inject(method = "tick", at = @At("HEAD"))
private void damageOnWater(CallbackInfo ci) {
if (TraitStates.hasTrait((PlayerEntity)(Object)this, AbilityMod.TRAIT_FEAR_OF_WATER) && isWet()) {
if (ServerState.hasTrait((PlayerEntity)(Object)this, AbilityMod.TRAIT_FEAR_OF_WATER) && isWet()) {
damage(getDamageSources().magic(), 3);
}
}

@Inject(method = "eatFood", at = @At("RETURN"))
private void poisonOnRotten(World world, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
if (stack.getItem().equals(Items.ROTTEN_FLESH) &&
ServerState.hasTrait((PlayerEntity)(Object)this, AbilityMod.TRAIT_HARMFUL_ROTTEN_FLESH)) {
if (ServerState.hasTrait((PlayerEntity)(Object)this, AbilityMod.TRAIT_INVERT_EFFECTS)) {
addStatusEffect(new StatusEffectInstance(StatusEffects.REGENERATION, 30 * 20));
} else {
addStatusEffect(new StatusEffectInstance(StatusEffects.POISON, 30 * 20));
}
}
}
}
41 changes: 41 additions & 0 deletions src/main/java/net/sigmarik/abilitymod/mixin/StatusEffectMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.sigmarik.abilitymod.mixin;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.ServerState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(StatusEffect.class)
public abstract class StatusEffectMixin {
@Inject(method = "applyUpdateEffect", at = @At("HEAD"), cancellable = true)
private void invertRegeneration(LivingEntity entity, int amplifier, CallbackInfo ci) {
if (entity instanceof PlayerEntity && ServerState.hasTrait((PlayerEntity)entity, AbilityMod.TRAIT_INVERT_EFFECTS)) {
if ((Object)this == StatusEffects.REGENERATION) {
if (entity.getHealth() > 1.0F) {
entity.damage(entity.getDamageSources().magic(), 1.0F);
}
ci.cancel();
} else if ((Object)this == StatusEffects.POISON) {
if (entity.getHealth() < entity.getMaxHealth()) {
entity.heal(1.0F);
}
ci.cancel();
}
}
}

@Redirect(method = "applyInstantEffect", at = @At(
value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isUndead()Z"))
private boolean traitedIsUndead(LivingEntity entity) {
return entity.isUndead() ||
(entity instanceof PlayerEntity &&
ServerState.hasTrait((PlayerEntity)entity, AbilityMod.TRAIT_INVERT_EFFECTS));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net.sigmarik.abilitymod.mixin;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.TargetPredicate;
import net.minecraft.entity.player.PlayerEntity;
import net.sigmarik.abilitymod.AbilityMod;
import net.sigmarik.abilitymod.util.ServerState;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(TargetPredicate.class)
public abstract class TargetPredicateMixin {
@Inject(method = "test", at = @At("HEAD"), cancellable = true)
private void checkUndead(@Nullable LivingEntity baseEntity, LivingEntity targetEntity, CallbackInfoReturnable<Boolean> cir) {
if (baseEntity == null) return;
if (baseEntity.isUndead() &&
targetEntity instanceof PlayerEntity &&
ServerState.hasTrait((PlayerEntity)targetEntity, AbilityMod.TRAIT_IGNORED_BY_UNDEAD) &&
baseEntity.getAttacker() != targetEntity) {
cir.setReturnValue(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
import java.util.HashMap;
import java.util.UUID;

public class TraitStates extends PersistentState {
public class ServerState extends PersistentState {
public HashMap<UUID, NbtCompound> traits = new HashMap<>();


@Override
public NbtCompound writeNbt(NbtCompound nbt) {
nbt.put(AbilityMod.MOD_ID + ":player_traits", new NbtCompound());
Expand All @@ -27,8 +26,8 @@ public NbtCompound writeNbt(NbtCompound nbt) {
return nbt;
}

public static TraitStates createFromNbt(NbtCompound nbt) {
TraitStates states = new TraitStates();
public static ServerState createFromNbt(NbtCompound nbt) {
ServerState states = new ServerState();
states.traits.clear();

NbtCompound player_data = nbt.getCompound(AbilityMod.MOD_ID + ":player_traits");
Expand Down Expand Up @@ -69,16 +68,16 @@ public void setSilenced(UUID playerId, String trait, boolean silenced) {
}
}

public static TraitStates getTraitStates(MinecraftServer server) {
public static ServerState getTraitStates(MinecraftServer server) {
PersistentStateManager manager = server.getOverworld().getPersistentStateManager();

return manager.getOrCreate(TraitStates::createFromNbt, TraitStates::new, AbilityMod.MOD_ID);
return manager.getOrCreate(ServerState::createFromNbt, ServerState::new, AbilityMod.MOD_ID);
}

public static boolean hasTrait(PlayerEntity player, String trait) {
if (player.getServer() == null) return false;

TraitStates states = getTraitStates(player.getServer());
ServerState states = getTraitStates(player.getServer());

if (!states.traits.containsKey(player.getUuid())) return false;
NbtCompound playerTraitsNbt = states.traits.get(player.getUuid());
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/abilitymod.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"EnderPearlEntityMixin",
"EnderPearlItemMixin",
"EndermanEntityMixin",
"PlayerEntityMixin"
"PlayerEntityMixin",
"TargetPredicateMixin",
"StatusEffectMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit a912f74

Please sign in to comment.