Shrieker tweaks + Game Rules

This commit is contained in:
ItsBlackGear 2022-07-24 16:41:41 -04:00
parent 0df5f73a09
commit 71d03eb2d4
13 changed files with 95 additions and 26 deletions

View file

@ -7,6 +7,7 @@ import com.cursedcauldron.wildbackport.common.registry.WBBlockEntities;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.registry.WBEnchantments;
import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import com.cursedcauldron.wildbackport.common.registry.WBGameRules;
import com.cursedcauldron.wildbackport.common.registry.WBItems;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.cursedcauldron.wildbackport.common.registry.WBPositionSources;
@ -53,6 +54,8 @@ public class WildBackport {
WBTreeDecorators.DECORATORS.register();
WBTrunkPlacers.PLACERS.register();
WBGameRules.setup();
// Tags
WBBiomeTags.TAGS.bootstrap();
WBBlockTags.TAGS.bootstrap();

View file

@ -10,6 +10,7 @@ import com.cursedcauldron.wildbackport.common.entities.warden.WardenSpawnHelper;
import com.cursedcauldron.wildbackport.common.entities.warden.WardenSpawnTracker;
import com.cursedcauldron.wildbackport.common.registry.WBBlockEntities;
import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import com.cursedcauldron.wildbackport.common.registry.WBGameRules;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntities;
import com.cursedcauldron.wildbackport.common.tag.WBGameEventTags;
import com.mojang.serialization.Dynamic;
@ -27,7 +28,6 @@ import net.minecraft.tags.TagKey;
import net.minecraft.util.Mth;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -81,7 +81,7 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
@Override
public TagKey<GameEvent> getListenableEvents() {
return WBGameEventTags.WARDEN_CAN_LISTEN;
return WBGameEventTags.SHRIEKER_CAN_LISTEN;
}
@Override
@ -151,8 +151,7 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
private boolean canRespond(ServerLevel level) {
//TODO: add gamerule for warden spawning
return this.getBlockState().getValue(SculkShriekerBlock.CAN_SUMMON) && level.getDifficulty() != Difficulty.PEACEFUL;
return this.getBlockState().getValue(SculkShriekerBlock.CAN_SUMMON) && level.getDifficulty() != Difficulty.PEACEFUL && level.getGameRules().getBoolean(WBGameRules.DO_WARDEN_SPAWNING);
}
public void tryRespond(ServerLevel level) {

View file

@ -1,6 +1,6 @@
package com.cursedcauldron.wildbackport.common.entities.brain;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.ForgetAttackTargetTask;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.ForgetAttackTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Digging;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Dismount;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Emerging;
@ -111,7 +111,7 @@ public class WardenBrain {
}
private static void initFightActivity(Warden warden, Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(DIG_COOLDOWN_SETTER, new ForgetAttackTargetTask<>(target -> {
brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(DIG_COOLDOWN_SETTER, new ForgetAttackTarget<>(target -> {
return !warden.getAngriness().isAngry() || !warden.isValidTarget(target);
}, WardenBrain::onTargetInvalid, false), new SetEntityLookTarget(target -> {
return isTarget(warden, target);

View file

@ -12,12 +12,12 @@ import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
public class ForgetAttackTargetTask<E extends Mob> extends Behavior<E> {
public class ForgetAttackTarget<E extends Mob> extends Behavior<E> {
private final Predicate<LivingEntity> stopAttackingWhen;
private final BiConsumer<E, LivingEntity> onTargetErased;
private final boolean canGrowTiredOfTryingToReachTarget;
public ForgetAttackTargetTask(Predicate<LivingEntity> stopAttackingWhen, BiConsumer<E, LivingEntity> onTargetEased, boolean canGrowTiredOfTryingToReachTarget) {
public ForgetAttackTarget(Predicate<LivingEntity> stopAttackingWhen, BiConsumer<E, LivingEntity> onTargetEased, boolean canGrowTiredOfTryingToReachTarget) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryStatus.REGISTERED));
this.stopAttackingWhen = stopAttackingWhen;
this.onTargetErased = onTargetEased;

View file

@ -24,10 +24,10 @@ public class Roar extends Behavior<Warden> {
protected void start(ServerLevel level, Warden warden, long time) {
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.ROAR_SOUND_DELAY.get(), Unit.INSTANCE, 25L);
warden.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
LivingEntity entity = warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).get();
BehaviorUtils.lookAtEntity(warden, entity);
LivingEntity target = warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).get();
BehaviorUtils.lookAtEntity(warden, target);
warden.setPose(Poses.ROARING.get());
warden.increaseAngerAt(entity, 20, false);
warden.increaseAngerAt(target, 20, false);
}
@Override

View file

@ -54,20 +54,20 @@ public class SonicBoom extends Behavior<Warden> {
if (!warden.getBrain().hasMemoryValue(WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get()) && !warden.getBrain().hasMemoryValue(WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get())) {
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(), Unit.INSTANCE, DURATION - TICKS_BEFORE_PLAYING_SOUND);
warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).filter(warden::isValidTarget).filter(target -> MobUtils.closerThan(warden, target, 15.0D, 20.0D)).ifPresent(target -> {
Vec3 wardenPos = warden.position().add(0.0D, 1.6F, 0.0D);
Vec3 distance = target.getEyePosition().subtract(wardenPos);
Vec3 source = warden.position().add(0.0D, 1.6F, 0.0D);
Vec3 distance = target.getEyePosition().subtract(source);
Vec3 position = distance.normalize();
for (int i = 1; i < Mth.floor(distance.length()) + 7; i++) {
Vec3 rayCharge = wardenPos.add(position.scale(i));
level.sendParticles(WBParticleTypes.SONIC_BOOM.get(), rayCharge.x, rayCharge.y, rayCharge.z, 1, 0.0D, 0.0D, 0.0D, 0.0D);
for(int i = 1; i < Mth.floor(distance.length()) + 7; ++i) {
Vec3 charge = source.add(position.scale(i));
level.sendParticles(WBParticleTypes.SONIC_BOOM.get(), charge.x, charge.y, charge.z, 1, 0.0D, 0.0D, 0.0D, 0.0D);
}
warden.playSound(WBSoundEvents.WARDEN_SONIC_BOOM, 3.0F, 1.0F);
target.hurt(sonicBoom(warden), 10.0F);
double yForce = 0.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double xzForce = 2.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
target.push(position.x * xzForce, position.y * yForce, position.z * xzForce);
double yKnockback = 0.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double xzKnockback = 2.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
target.push(position.x() * xzKnockback, position.y() * yKnockback, position.z() * xzKnockback);
});
}
}

View file

@ -0,0 +1,15 @@
package com.cursedcauldron.wildbackport.common.registry;
import com.cursedcauldron.wildbackport.core.mixin.access.BooleanValueAccessor;
import com.cursedcauldron.wildbackport.core.mixin.access.GameRulesAccessor;
import net.minecraft.world.level.GameRules;
public class WBGameRules {
public static void setup() {}
public static final GameRules.Key<GameRules.BooleanValue> DO_WARDEN_SPAWNING = create("doWardenSpawning", GameRules.Category.SPAWNING, BooleanValueAccessor.callCreate(true));
private static <T extends GameRules.Value<T>> GameRules.Key<T> create(String key, GameRules.Category category, GameRules.Type<T> type) {
return GameRulesAccessor.callRegister(key, category, type);
}
}

View file

@ -0,0 +1,13 @@
package com.cursedcauldron.wildbackport.core.mixin.access;
import net.minecraft.world.level.GameRules;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(GameRules.BooleanValue.class)
public interface BooleanValueAccessor {
@Invoker
static GameRules.Type<GameRules.BooleanValue> callCreate(boolean bl) {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,16 @@
package com.cursedcauldron.wildbackport.core.mixin.access;
import net.minecraft.world.level.GameRules;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.Map;
@Mixin(GameRules.class)
public interface GameRulesAccessor {
@Invoker
static <T extends GameRules.Value<T>> GameRules.Key<T> callRegister(String string, GameRules.Category category, GameRules.Type<T> type) {
throw new UnsupportedOperationException();
}
}

View file

@ -1,15 +1,37 @@
package com.cursedcauldron.wildbackport.core.mixin.common;
import com.cursedcauldron.wildbackport.common.entities.access.Vibration;
import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.SculkSensorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.SculkSensorBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.GameEventListener;
import net.minecraft.world.level.gameevent.vibrations.VibrationListener;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SculkSensorBlockEntity.class)
public class SculkSensorBlockEntityMixin extends BlockEntity {
@Shadow @Final private VibrationListener listener;
public SculkSensorBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Inject(method = "onSignalReceive", at = @At("HEAD"))
private void receiveSignal(Level level, GameEventListener listener, GameEvent event, int delay, CallbackInfo ci) {
if (!level.isClientSide() && SculkSensorBlock.canActivate(this.getBlockState())) {
Vibration.Instance instance = Vibration.Instance.of(this.listener);
level.gameEvent(instance.getEntity(), WBGameEvents.SCULK_SENSOR_TENDRILS_CLICKING.get(), instance.getPos());
}
}
}

View file

@ -16,12 +16,10 @@ import java.util.Random;
@Mixin(Slime.class)
public class SlimeMixin {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/LevelAccessor;getDifficulty()Lnet/minecraft/world/Difficulty;", shift = At.Shift.AFTER), method = "checkSlimeSpawnRules", cancellable = true)
private static void WB$checkSlimeSpawnRules(EntityType<Slime> entityType, LevelAccessor levelAccessor, MobSpawnType mobSpawnType, BlockPos blockPos, Random randomSource, CallbackInfoReturnable<Boolean> cir) {
if (levelAccessor.getBiome(blockPos).is(WBBiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && blockPos.getY() > 50 && blockPos.getY() < 70 && randomSource.nextFloat() < 0.5F && randomSource.nextFloat() < levelAccessor.getMoonBrightness() && levelAccessor.getMaxLocalRawBrightness(blockPos) <= randomSource.nextInt(8)) {
cir.setReturnValue(Mob.checkMobSpawnRules(entityType, levelAccessor, mobSpawnType, blockPos, randomSource));
private static void WB$checkSlimeSpawnRules(EntityType<Slime> entity, LevelAccessor level, MobSpawnType spawn, BlockPos pos, Random random, CallbackInfoReturnable<Boolean> cir) {
if (level.getBiome(pos).is(WBBiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < level.getMoonBrightness() && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
cir.setReturnValue(Mob.checkMobSpawnRules(entity, level, spawn, pos, random));
}
}
}
}

View file

@ -91,5 +91,6 @@
"commands.warden_spawn_tracker.clear.success.single": "Removed warnings from %s",
"commands.warden_spawn_tracker.clear.success.multiple": "Removed warnings from %s players",
"death.attack.sonic_boom": "%1$s was obliterated by a sonically-charged shriek",
"death.attack.sonic_boom.player": "%1$s was obliterated by a sonically-charged shriek whilst trying to escape %2$s"
"death.attack.sonic_boom.player": "%1$s was obliterated by a sonically-charged shriek whilst trying to escape %2$s",
"gamerule.doWardenSpawning": "Spawn Wardens"
}

View file

@ -6,10 +6,12 @@
"mixins": [
"access.ActivityAccessor",
"access.AxeItemAccessor",
"access.BooleanValueAccessor",
"access.CriteriaTriggersAccessor",
"access.DamageSourceAccessor",
"access.DoorBlockAccessor",
"access.FireBlockAccessor",
"access.GameRulesAccessor",
"access.MemoryModuleTypeAccessor",
"access.MobEffectAccessor",
"access.ModelPartAccessor",