From a51c3acb96d076409d89be88745d4858e63d8dba Mon Sep 17 00:00:00 2001 From: haykam821 <24855774+haykam821@users.noreply.github.com> Date: Thu, 28 Nov 2024 01:07:46 -0500 Subject: [PATCH] Add the stop spectating entity rule type --- .../plasmid/api/game/rule/GameRuleType.java | 1 + .../game/rule/ServerPlayerEntityMixin.java | 20 +++++++++++++++++++ .../xyz/nucleoid/plasmid/test/TestGame.java | 13 +++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/xyz/nucleoid/plasmid/api/game/rule/GameRuleType.java b/src/main/java/xyz/nucleoid/plasmid/api/game/rule/GameRuleType.java index 75ebc2b5..aae7ef6e 100644 --- a/src/main/java/xyz/nucleoid/plasmid/api/game/rule/GameRuleType.java +++ b/src/main/java/xyz/nucleoid/plasmid/api/game/rule/GameRuleType.java @@ -111,6 +111,7 @@ public final class GameRuleType { .enforces(CoralDeathEvent.EVENT, result -> (world, pos, from, to) -> result); public static final GameRuleType DISMOUNT_VEHICLE = GameRuleType.create(); + public static final GameRuleType STOP_SPECTATING_ENTITY = GameRuleType.create(); public static final GameRuleType PLAYER_PROJECTILE_KNOCKBACK = GameRuleType.create(); public static final GameRuleType TRIDENTS_LOYAL_IN_VOID = GameRuleType.create(); public static final GameRuleType MODIFY_INVENTORY = GameRuleType.create(); diff --git a/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/ServerPlayerEntityMixin.java b/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/ServerPlayerEntityMixin.java index 897a7dc0..233d9e75 100644 --- a/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/ServerPlayerEntityMixin.java +++ b/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/ServerPlayerEntityMixin.java @@ -1,6 +1,8 @@ package xyz.nucleoid.plasmid.mixin.game.rule; +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.mojang.authlib.GameProfile; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; @@ -9,7 +11,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import xyz.nucleoid.plasmid.api.game.rule.GameRuleType; import xyz.nucleoid.plasmid.impl.game.manager.GameSpaceManagerImpl; +import xyz.nucleoid.stimuli.event.EventResult; @Mixin(ServerPlayerEntity.class) public abstract class ServerPlayerEntityMixin extends PlayerEntity { @@ -17,6 +21,22 @@ private ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfil super(world, pos, yaw, profile); } + @WrapWithCondition( + method = "tick", + // The targeted call handles shifting to stop spectating + // The other call handles dead entities, which should always stop being spectated + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;setCameraEntity(Lnet/minecraft/entity/Entity;)V", ordinal = 0) + ) + private boolean preventStopSpectatingEntity(ServerPlayerEntity player, Entity entity) { + var gameSpace = GameSpaceManagerImpl.get().byPlayer(player); + + if (gameSpace != null && gameSpace.getBehavior().testRule(GameRuleType.STOP_SPECTATING_ENTITY) == EventResult.DENY) { + return false; + } + + return true; + } + @Inject(method = "isPvpEnabled", at = @At("HEAD"), cancellable = true) private void allowPvPInGames(CallbackInfoReturnable cir) { var gameSpace = GameSpaceManagerImpl.get().byPlayer(this); diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java index ab4d6001..4da5a263 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java @@ -6,8 +6,10 @@ import net.minecraft.block.ButtonBlock; import net.minecraft.block.LeavesBlock; import net.minecraft.block.enums.BlockFace; +import net.minecraft.entity.EntityType; import net.minecraft.item.Item; import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; import net.minecraft.scoreboard.AbstractTeam; import net.minecraft.screen.ScreenTexts; import net.minecraft.server.network.ServerPlayerEntity; @@ -18,11 +20,13 @@ import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; import net.minecraft.world.GameRules; import xyz.nucleoid.fantasy.RuntimeWorldConfig; import xyz.nucleoid.map_templates.BlockBounds; +import xyz.nucleoid.map_templates.MapEntity; import xyz.nucleoid.map_templates.MapTemplate; import xyz.nucleoid.plasmid.api.game.*; import xyz.nucleoid.plasmid.api.game.common.team.*; @@ -152,7 +156,7 @@ private static GameResult startGame(GameSpace gameSpace) { long currentTime = gameSpace.getTime(); activity.deny(GameRuleType.PVP).allow(GameRuleType.MODIFY_ARMOR); activity.deny(GameRuleType.FALL_DAMAGE).deny(GameRuleType.HUNGER); - activity.deny(GameRuleType.THROW_ITEMS); + activity.deny(GameRuleType.THROW_ITEMS).deny(GameRuleType.STOP_SPECTATING_ENTITY); activity.deny(GameRuleType.INTERACTION).allow(GameRuleType.USE_BLOCKS); @@ -214,6 +218,13 @@ private static MapTemplate generateMapTemplate(BlockState state) { var edge = new BlockPos(max.getX(), max.getY() + 1, max.getZ()); template.setBlockState(edge, BUTTON); + var armorStandNbt = new NbtCompound(); + armorStandNbt.putString("id", EntityType.getId(EntityType.ARMOR_STAND).toString()); + armorStandNbt.putBoolean("NoGravity", true); + + var armorStandPos = Vec3d.ofBottomCenter(edge.offset(Direction.WEST)); + template.addEntity(new MapEntity(armorStandPos, armorStandNbt)); + for (var pos : bounds) { template.setBlockState(pos, state); }