Skip to content

Commit

Permalink
fix: Update vanish support
Browse files Browse the repository at this point in the history
  • Loading branch information
gabizou committed Jul 17, 2024
1 parent 994fb27 commit 23bcf33
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
Expand All @@ -38,11 +39,20 @@
public abstract class EntitySelectorMixin {

@Shadow @Final @Mutable public static Predicate<Entity> NO_SPECTATORS = entity -> {
if (entity instanceof VanishableBridge && ((VanishableBridge) entity).bridge$vanishState().invisible()) {
if (entity instanceof VanishableBridge vb && vb.bridge$vanishState().invisible()) {
// Sponge: Count vanished entities as spectating
return false;
}
return !entity.isSpectator();
};

@Shadow @Final @Mutable public static Predicate<Entity> NO_CREATIVE_OR_SPECTATOR = $$0 -> {
if ($$0 instanceof VanishableBridge vb && vb.bridge$vanishState().invisible()) {
// Sponge: Count vanished entities as spectating
return false;
}
return !($$0 instanceof Player) || !$$0.isSpectator() && !((Player)$$0).isCreative();
};


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.mixin.core.world.entity.ai.sensing;

import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.sensing.NearestLivingEntitySensor;
import net.minecraft.world.phys.AABB;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.common.bridge.data.VanishableBridge;

import java.util.List;
import java.util.function.Predicate;

@Mixin(NearestLivingEntitySensor.class)
public class NearestLivingEntitySensorMixin<T extends LivingEntity> extends SensorMixin<T> {

@Redirect(method = "doTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;"))
private <T extends Entity> List<T> impl$ignoreVanishedEntities(
final ServerLevel instance, final Class<T> aClass, final AABB aabb,
final Predicate<? super T> predicate
) {
return instance.getEntitiesOfClass(aClass, aabb, entity -> {
if (entity instanceof VanishableBridge v) {
final var state = v.bridge$vanishState();
if (state.invisible() || state.untargetable()) {
return false;
}
}
return predicate.test(entity);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.mixin.core.world.entity.ai.sensing;

import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.sensing.Sensor;
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;
import org.spongepowered.common.bridge.data.VanishableBridge;

@Mixin(Sensor.class)
public class SensorMixin<E extends LivingEntity> {

@Inject(method = {
"isEntityTargetable",
"isEntityAttackable",
"isEntityAttackableIgnoringLineOfSight"
}, at = @At("HEAD"), cancellable = true)
private static void impl$cancelForVanishedEntities(LivingEntity $$0, LivingEntity $$1, CallbackInfoReturnable<Boolean> cir) {
final var vs = ((VanishableBridge) $$0).bridge$vanishState();
if (vs.invisible() && vs.untargetable()) {
cir.setReturnValue(false);
}
final var vsOther = ((VanishableBridge) $$1).bridge$vanishState();
if (vsOther.invisible() && vsOther.untargetable()) {
cir.setReturnValue(false);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import net.minecraft.world.phys.AABB;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.ResourceKey;
Expand All @@ -59,9 +60,14 @@
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.common.SpongeCommon;
import org.spongepowered.common.accessor.world.entity.MobAccessor;
import org.spongepowered.common.accessor.world.entity.item.FallingBlockEntityAccessor;
import org.spongepowered.common.bridge.data.VanishableBridge;
import org.spongepowered.common.bridge.world.level.LevelBridge;
import org.spongepowered.common.data.persistence.NBTTranslator;
import org.spongepowered.common.entity.projectile.UnknownProjectileSource;
Expand All @@ -75,7 +81,7 @@
@Mixin(net.minecraft.world.level.Level.class)
public abstract class LevelMixin implements LevelBridge, LevelAccessor {

// @formatter: off
//@formatter: off
@Mutable @Shadow @Final private Holder<DimensionType> dimensionTypeRegistration;
@Shadow protected float oRainLevel;
@Shadow protected float rainLevel;
Expand All @@ -98,8 +104,6 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
// @formatter on




@Override
public boolean bridge$isFake() {
return this.isClientSide();
Expand All @@ -113,13 +117,14 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
}

@SuppressWarnings("unchecked")
@Override
public <E extends org.spongepowered.api.entity.Entity> E bridge$createEntity(
final DataContainer dataContainer,
final @Nullable Vector3d position,
final @Nullable Predicate<Vector3d> positionCheck) throws IllegalArgumentException, IllegalStateException {
final DataContainer dataContainer,
final @Nullable Vector3d position,
final @Nullable Predicate<Vector3d> positionCheck) throws IllegalArgumentException, IllegalStateException {

final EntityType<@NonNull ?> type = dataContainer.getRegistryValue(Constants.Entity.TYPE, RegistryTypes.ENTITY_TYPE)
.orElseThrow(() -> new IllegalArgumentException("DataContainer does not contain a valid entity type."));
.orElseThrow(() -> new IllegalArgumentException("DataContainer does not contain a valid entity type."));
final Vector3d proposedPosition;
if (position == null) {
proposedPosition = DataUtil.getPosition3d(dataContainer, Constants.Sponge.SNAPSHOT_WORLD_POSITION);
Expand All @@ -129,9 +134,9 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {

if (positionCheck != null && !positionCheck.test(proposedPosition)) {
throw new IllegalArgumentException(String.format("Position (%.2f, %.2f, %.2f) is not a valid position in this context.",
proposedPosition.x(),
proposedPosition.y(),
proposedPosition.z()));
proposedPosition.x(),
proposedPosition.y(),
proposedPosition.z()));
}

final @Nullable Vector3d rotation;
Expand All @@ -150,15 +155,15 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {

final Entity createdEntity = this.bridge$createEntity(type, position, false);
dataContainer.getView(Constants.Sponge.UNSAFE_NBT)
.map(NBTTranslator.INSTANCE::translate)
.ifPresent(x -> {
final net.minecraft.world.entity.Entity e = ((net.minecraft.world.entity.Entity) createdEntity);
// mimicing Entity#restoreFrom
x.remove("Dimension");
e.load(x);
// position needs a reset
e.moveTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z());
});
.map(NBTTranslator.INSTANCE::translate)
.ifPresent(x -> {
final net.minecraft.world.entity.Entity e = ((net.minecraft.world.entity.Entity) createdEntity);
// mimicing Entity#restoreFrom
x.remove("Dimension");
e.load(x);
// position needs a reset
e.moveTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z());
});
if (rotation != null) {
createdEntity.setRotation(rotation);
}
Expand Down Expand Up @@ -225,7 +230,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
if (naturally && entity instanceof Mob) {
// Adding the default equipment
final DifficultyInstance difficulty = this.shadow$getCurrentDifficultyAt(new BlockPos((int) x, (int) y, (int) z));
((MobAccessor)entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty);
((MobAccessor) entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty);
}

if (entity instanceof Painting) {
Expand All @@ -236,4 +241,29 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {

return (E) entity;
}

@Inject(method = {
"getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
"getEntities(Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
}, at = @At("RETURN"))
private void impl$IgnoreTargetingOfVanishedEntities(
final @Coerce Object entityIn, final AABB aabb,
final Predicate<?> filter, final CallbackInfoReturnable<List<net.minecraft.world.entity.Entity>> cir
) {
if (this.bridge$isFake()) {
return;
}
final List<net.minecraft.world.entity.Entity> entities = cir.getReturnValue();
if (entities == null || entities.isEmpty()) {
return;
}
entities.removeIf(entity -> {
if (entity instanceof VanishableBridge vb) {
final var state = vb.bridge$vanishState();
return state.invisible() && state.untargetable();
}
return false;
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public abstract class LevelMixin_Tracker implements LevelBridge, LevelAccessor {
tileEntity.tick();
}

@SuppressWarnings("InvalidInjectorMethodSignature")
@Inject(method = {
"getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
"getEntities(Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
Expand Down
2 changes: 2 additions & 0 deletions src/mixins/resources/mixins.sponge.core.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
"world.entity.ai.goal.GoalSelectorMixin",
"world.entity.ai.goal.RangedAttackGoalMixin",
"world.entity.ai.goal.RunAroundLikeCrazyGoalMixin",
"world.entity.ai.sensing.NearestLivingEntitySensorMixin",
"world.entity.ai.sensing.SensorMixin",
"world.entity.animal.AnimalMixin",
"world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin",
"world.entity.animal.OcelotMixin",
Expand Down

0 comments on commit 23bcf33

Please sign in to comment.