mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-24 08:38:17 -05:00
Fix crash when beehive is broken by fake player (#3190)
* Fix crash when beehive is broken by fake player When a beehive is broken, every nearby bee targets a random player. However, if there are no nearby players, the game crashes. This should not occur under normal (vanilla) conditions. However, if a beehive is broken by a fake player there are no players in range, and so we see a crash. * Checkstyle, my beloved * Remove public modifier * See see see
This commit is contained in:
parent
737a6ee8bf
commit
4b6b93f0b1
3 changed files with 72 additions and 0 deletions
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.fabricmc.fabric.mixin.event.interaction;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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.LocalCapture;
|
||||||
|
|
||||||
|
import net.minecraft.block.BeehiveBlock;
|
||||||
|
import net.minecraft.entity.passive.BeeEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@Mixin(BeehiveBlock.class)
|
||||||
|
class BeehiveBlockMixin {
|
||||||
|
@Inject(
|
||||||
|
method = "angerNearbyBees",
|
||||||
|
cancellable = true,
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE_ASSIGN",
|
||||||
|
target = "Lnet/minecraft/world/World;getNonSpectatingEntities(Ljava/lang/Class;Lnet/minecraft/util/math/Box;)Ljava/util/List;",
|
||||||
|
ordinal = 1 // Only capture the PlayerEntity call.
|
||||||
|
),
|
||||||
|
locals = LocalCapture.CAPTURE_FAILHARD
|
||||||
|
)
|
||||||
|
private void afterNearbyBeesPlayers(World world, BlockPos pos, CallbackInfo ci, List<BeeEntity> bees, List<PlayerEntity> players) {
|
||||||
|
// If a fake player broke the beehive, there will be no nearby players. This causes a crash later on as we try
|
||||||
|
// to pick a random player - we early return to avoid this.
|
||||||
|
if (players.isEmpty()) ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
"package": "net.fabricmc.fabric.mixin.event.interaction",
|
"package": "net.fabricmc.fabric.mixin.event.interaction",
|
||||||
"compatibilityLevel": "JAVA_16",
|
"compatibilityLevel": "JAVA_16",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"BeehiveBlockMixin",
|
||||||
"PlayerAdvancementTrackerMixin",
|
"PlayerAdvancementTrackerMixin",
|
||||||
"ServerPlayerEntityMixin",
|
"ServerPlayerEntityMixin",
|
||||||
"ServerPlayerInteractionManagerMixin",
|
"ServerPlayerInteractionManagerMixin",
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
package net.fabricmc.fabric.test.event.interaction;
|
package net.fabricmc.fabric.test.event.interaction;
|
||||||
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.ItemUsageContext;
|
import net.minecraft.item.ItemUsageContext;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.test.GameTest;
|
import net.minecraft.test.GameTest;
|
||||||
import net.minecraft.test.TestContext;
|
import net.minecraft.test.TestContext;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
@ -60,4 +62,23 @@ public class FakePlayerTests {
|
||||||
context.assertTrue(signStack.isEmpty(), "Sign stack was not emptied");
|
context.assertTrue(signStack.isEmpty(), "Sign stack was not emptied");
|
||||||
context.complete();
|
context.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try breaking a beehive with a fake player (see {@code BeehiveBlockMixin}).
|
||||||
|
*/
|
||||||
|
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
|
||||||
|
public void testFakePlayerBreakBeehive(TestContext context) {
|
||||||
|
BlockPos basePos = new BlockPos(0, 1, 0);
|
||||||
|
context.setBlockState(basePos, Blocks.BEEHIVE);
|
||||||
|
context.spawnEntity(EntityType.BEE, basePos.up());
|
||||||
|
|
||||||
|
ServerPlayerEntity fakePlayer = FakePlayer.get(context.getWorld());
|
||||||
|
|
||||||
|
BlockPos fakePlayerPos = context.getAbsolutePos(basePos.add(2, 0, 2));
|
||||||
|
fakePlayer.setPosition(fakePlayerPos.getX(), fakePlayerPos.getY(), fakePlayerPos.getZ());
|
||||||
|
|
||||||
|
context.assertTrue(fakePlayer.interactionManager.tryBreakBlock(context.getAbsolutePos(basePos)), "Block was not broken");
|
||||||
|
context.expectBlock(Blocks.AIR, basePos);
|
||||||
|
context.complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue