Skip to content

Commit be9d7de

Browse files
committed
fix: Update vanish support
1 parent f2fd4ff commit be9d7de

File tree

7 files changed

+184
-24
lines changed

7 files changed

+184
-24
lines changed

.editorconfig

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
root = true
2+
3+
4+
[mixins.*.json]
5+
tab_width = 4
6+
indent_size = tab
7+
indent_style = space

src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntitySelectorMixin.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import net.minecraft.world.entity.Entity;
2828
import net.minecraft.world.entity.EntitySelector;
29+
import net.minecraft.world.entity.player.Player;
2930
import org.spongepowered.asm.mixin.Final;
3031
import org.spongepowered.asm.mixin.Mixin;
3132
import org.spongepowered.asm.mixin.Mutable;
@@ -38,11 +39,20 @@
3839
public abstract class EntitySelectorMixin {
3940

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

49+
@Shadow @Final @Mutable public static Predicate<Entity> NO_CREATIVE_OR_SPECTATOR = $$0 -> {
50+
if ($$0 instanceof VanishableBridge vb && vb.bridge$vanishState().invisible()) {
51+
// Sponge: Count vanished entities as spectating
52+
return false;
53+
}
54+
return !($$0 instanceof Player) || !$$0.isSpectator() && !((Player)$$0).isCreative();
55+
};
56+
57+
4858
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.mixin.core.world.entity.ai.sensing;
26+
27+
import net.minecraft.server.level.ServerLevel;
28+
import net.minecraft.world.entity.Entity;
29+
import net.minecraft.world.entity.LivingEntity;
30+
import net.minecraft.world.entity.ai.sensing.NearestLivingEntitySensor;
31+
import net.minecraft.world.phys.AABB;
32+
import org.spongepowered.asm.mixin.Mixin;
33+
import org.spongepowered.asm.mixin.injection.At;
34+
import org.spongepowered.asm.mixin.injection.Redirect;
35+
import org.spongepowered.common.bridge.data.VanishableBridge;
36+
37+
import java.util.List;
38+
import java.util.function.Predicate;
39+
40+
@Mixin(NearestLivingEntitySensor.class)
41+
public class NearestLivingEntitySensorMixin<T extends LivingEntity> extends SensorMixin<T> {
42+
43+
@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;"))
44+
private <T extends Entity> List<T> impl$ignoreVanishedEntities(
45+
final ServerLevel instance, final Class<T> aClass, final AABB aabb,
46+
final Predicate<? super T> predicate
47+
) {
48+
return instance.getEntitiesOfClass(aClass, aabb, entity -> {
49+
if (entity instanceof VanishableBridge v) {
50+
final var state = v.bridge$vanishState();
51+
if (state.invisible() || state.untargetable()) {
52+
return false;
53+
}
54+
}
55+
return predicate.test(entity);
56+
});
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.mixin.core.world.entity.ai.sensing;
26+
27+
import net.minecraft.world.entity.LivingEntity;
28+
import net.minecraft.world.entity.ai.sensing.Sensor;
29+
import org.spongepowered.asm.mixin.Mixin;
30+
import org.spongepowered.asm.mixin.injection.At;
31+
import org.spongepowered.asm.mixin.injection.Inject;
32+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
33+
import org.spongepowered.common.bridge.data.VanishableBridge;
34+
35+
@Mixin(Sensor.class)
36+
public class SensorMixin<E extends LivingEntity> {
37+
38+
@Inject(method = {
39+
"isEntityTargetable",
40+
"isEntityAttackable",
41+
"isEntityAttackableIgnoringLineOfSight"
42+
}, at = @At("HEAD"), cancellable = true)
43+
private static void impl$cancelForVanishedEntities(LivingEntity $$0, LivingEntity $$1, CallbackInfoReturnable<Boolean> cir) {
44+
final var vs = ((VanishableBridge) $$0).bridge$vanishState();
45+
if (vs.invisible() && vs.untargetable()) {
46+
cir.setReturnValue(false);
47+
}
48+
final var vsOther = ((VanishableBridge) $$1).bridge$vanishState();
49+
if (vsOther.invisible() && vsOther.untargetable()) {
50+
cir.setReturnValue(false);
51+
}
52+
}
53+
54+
}

src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java

+51-21
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import net.minecraft.world.level.dimension.DimensionType;
4747
import net.minecraft.world.level.storage.LevelData;
4848
import net.minecraft.world.level.storage.WritableLevelData;
49+
import net.minecraft.world.phys.AABB;
4950
import org.checkerframework.checker.nullness.qual.NonNull;
5051
import org.checkerframework.checker.nullness.qual.Nullable;
5152
import org.spongepowered.api.ResourceKey;
@@ -59,9 +60,14 @@
5960
import org.spongepowered.asm.mixin.Mixin;
6061
import org.spongepowered.asm.mixin.Mutable;
6162
import org.spongepowered.asm.mixin.Shadow;
63+
import org.spongepowered.asm.mixin.injection.At;
64+
import org.spongepowered.asm.mixin.injection.Coerce;
65+
import org.spongepowered.asm.mixin.injection.Inject;
66+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
6267
import org.spongepowered.common.SpongeCommon;
6368
import org.spongepowered.common.accessor.world.entity.MobAccessor;
6469
import org.spongepowered.common.accessor.world.entity.item.FallingBlockEntityAccessor;
70+
import org.spongepowered.common.bridge.data.VanishableBridge;
6571
import org.spongepowered.common.bridge.world.level.LevelBridge;
6672
import org.spongepowered.common.data.persistence.NBTTranslator;
6773
import org.spongepowered.common.entity.projectile.UnknownProjectileSource;
@@ -75,7 +81,7 @@
7581
@Mixin(net.minecraft.world.level.Level.class)
7682
public abstract class LevelMixin implements LevelBridge, LevelAccessor {
7783

78-
// @formatter: off
84+
//@formatter: off
7985
@Mutable @Shadow @Final private net.minecraft.resources.ResourceKey<DimensionType> dimensionTypeId;
8086
@Mutable @Shadow @Final private Holder<DimensionType> dimensionTypeRegistration;
8187
@Shadow protected float oRainLevel;
@@ -96,9 +102,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
96102
@Shadow public abstract net.minecraft.world.level.block.entity.@Nullable BlockEntity shadow$getBlockEntity(BlockPos p_175625_1_);
97103
@Shadow public abstract WorldBorder shadow$getWorldBorder();
98104
//@Shadow protected abstract void shadow$postGameEventInRadius(@javax.annotation.Nullable net.minecraft.world.entity.Entity $$0, GameEvent $$1, BlockPos $$2, int $$3);
99-
// @formatter on
100-
101-
105+
//@formatter on
102106

103107

104108
@Override
@@ -115,13 +119,14 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
115119
}
116120

117121
@SuppressWarnings("unchecked")
122+
@Override
118123
public <E extends org.spongepowered.api.entity.Entity> E bridge$createEntity(
119-
final DataContainer dataContainer,
120-
final @Nullable Vector3d position,
121-
final @Nullable Predicate<Vector3d> positionCheck) throws IllegalArgumentException, IllegalStateException {
124+
final DataContainer dataContainer,
125+
final @Nullable Vector3d position,
126+
final @Nullable Predicate<Vector3d> positionCheck) throws IllegalArgumentException, IllegalStateException {
122127

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

132137
if (positionCheck != null && !positionCheck.test(proposedPosition)) {
133138
throw new IllegalArgumentException(String.format("Position (%.2f, %.2f, %.2f) is not a valid position in this context.",
134-
proposedPosition.x(),
135-
proposedPosition.y(),
136-
proposedPosition.z()));
139+
proposedPosition.x(),
140+
proposedPosition.y(),
141+
proposedPosition.z()));
137142
}
138143

139144
final @Nullable Vector3d rotation;
@@ -152,15 +157,15 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
152157

153158
final Entity createdEntity = this.bridge$createEntity(type, position, false);
154159
dataContainer.getView(Constants.Sponge.UNSAFE_NBT)
155-
.map(NBTTranslator.INSTANCE::translate)
156-
.ifPresent(x -> {
157-
final net.minecraft.world.entity.Entity e = ((net.minecraft.world.entity.Entity) createdEntity);
158-
// mimicing Entity#restoreFrom
159-
x.remove("Dimension");
160-
e.load(x);
161-
// position needs a reset
162-
e.moveTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z());
163-
});
160+
.map(NBTTranslator.INSTANCE::translate)
161+
.ifPresent(x -> {
162+
final net.minecraft.world.entity.Entity e = ((net.minecraft.world.entity.Entity) createdEntity);
163+
// mimicing Entity#restoreFrom
164+
x.remove("Dimension");
165+
e.load(x);
166+
// position needs a reset
167+
e.moveTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z());
168+
});
164169
if (rotation != null) {
165170
createdEntity.setRotation(rotation);
166171
}
@@ -227,7 +232,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
227232
if (naturally && entity instanceof Mob) {
228233
// Adding the default equipment
229234
final DifficultyInstance difficulty = this.shadow$getCurrentDifficultyAt(new BlockPos((int) x, (int) y, (int) z));
230-
((MobAccessor)entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty);
235+
((MobAccessor) entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty);
231236
}
232237

233238
if (entity instanceof Painting) {
@@ -238,4 +243,29 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor {
238243

239244
return (E) entity;
240245
}
246+
247+
@Inject(method = {
248+
"getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
249+
"getEntities(Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
250+
}, at = @At("RETURN"))
251+
private void impl$IgnoreTargetingOfVanishedEntities(
252+
final @Coerce Object entityIn, final AABB aabb,
253+
final Predicate<?> filter, final CallbackInfoReturnable<List<net.minecraft.world.entity.Entity>> cir
254+
) {
255+
if (this.bridge$isFake()) {
256+
return;
257+
}
258+
final List<net.minecraft.world.entity.Entity> entities = cir.getReturnValue();
259+
if (entities == null || entities.isEmpty()) {
260+
return;
261+
}
262+
entities.removeIf(entity -> {
263+
if (entity instanceof VanishableBridge vb) {
264+
final var state = vb.bridge$vanishState();
265+
return state.invisible() && state.untargetable();
266+
}
267+
return false;
268+
});
269+
}
270+
241271
}

src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public abstract class LevelMixin_Tracker implements LevelBridge, LevelAccessor {
9393
tileEntity.tick();
9494
}
9595

96-
@SuppressWarnings("InvalidInjectorMethodSignature")
9796
@Inject(method = {
9897
"getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
9998
"getEntities(Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",

src/mixins/resources/mixins.sponge.core.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020
"block.BedBlockMixin",
2121
"block.BlockMixin",
2222
"block.DyeColorBlockPropertiesMixin",
23-
"commands.execution.tasks.ExecuteCommandMixin",
2423
"commands.CommandsMixin",
2524
"commands.CommandSourceMixin",
2625
"commands.CommandSourceStackMixin",
2726
"commands.arguments.ComponentArgumentMixin",
2827
"commands.arguments.DimensionArgumentMixin",
2928
"commands.arguments.selector.EntitySelectorParserMixin",
29+
"commands.execution.tasks.ExecuteCommandMixin",
3030
"core.MappedRegistryMixin",
3131
"core.Vec3iMixin",
3232
"core.dispenser.AbstractProjectileDispenseBehaviorMixin",
@@ -117,6 +117,8 @@
117117
"world.entity.ai.goal.GoalMixin",
118118
"world.entity.ai.goal.GoalSelectorMixin",
119119
"world.entity.ai.goal.RunAroundLikeCrazyGoalMixin",
120+
"world.entity.ai.sensing.NearestLivingEntitySensorMixin",
121+
"world.entity.ai.sensing.SensorMixin",
120122
"world.entity.animal.AnimalMixin",
121123
"world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin",
122124
"world.entity.animal.OcelotMixin",

0 commit comments

Comments
 (0)