/* * Copyright 2025-2026 R3944Realms * * 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 top.r3944realms.eroticdungeongame.mixin.minecraft; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.game.ClientboundRemoveMobEffectPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.tags.BlockTags; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import top.r3944realms.eroticdungeongame.api.workspace.Services; import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity; import top.r3944realms.eroticdungeongame.content.entity.SeatEntity; import top.r3944realms.eroticdungeongame.core.service.SeatService; import top.r3944realms.eroticdungeongame.util.IEDGEntity; import java.util.Objects; import java.util.Optional; @Mixin(ServerPlayer.class) public abstract class MixinServerPlayer extends Player implements IEDGEntity { public MixinServerPlayer(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { super(level, pos, yRot, gameProfile); } @Shadow public abstract ServerLevel serverLevel(); @Shadow public ServerGamePacketListenerImpl connection; @Shadow public abstract boolean isCreative(); @WrapMethod( method = "stopRiding" ) private void edg$redefineStopRiding(Operation original) { ServerPlayer player = ServerPlayer.class.cast(this); Services.WORK_SPACE.tryToDoIfInDevice(player, data -> { if (data.getDeviceMainBlockPos() == null || !(level().getBlockEntity(data.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity seatBe) || !seatBe.hasLockCode()) { original.call(); } else { Optional playerSeat = SeatService.getPlayerSeat(player); if (playerSeat.isEmpty() || playerSeat.get().isRemoved()) { original.call(); } } }, original::call ); } @SuppressWarnings("AddedMixinMembersNamePattern") @Override public void releaseEntityFromEDGDevice(long lock, boolean forced) { ServerPlayer player = ServerPlayer.class.cast(this); Services.WORK_SPACE.tryToDoIfInDevice(player, data -> { if (data.getDeviceMainBlockPos() != null && level().getBlockEntity(data.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity seatBe) { if (isCreative() || forced || (seatBe.hasLockCode() && Objects.equals(seatBe.getLockCode(), lock)) || !seatBe.hasLockCode()) { Entity entity = this.getVehicle(); if (entity != null && !this.level().isClientSide) { Vec3 vec3; if (this.isRemoved()) { vec3 = this.position(); } else if (!entity.isRemoved() && !this.level().getBlockState(entity.blockPosition()).is(BlockTags.PORTALS)) { vec3 = entity.getDismountLocationForPassenger(this); } else { double d0 = Math.max(this.getY(), entity.getY()); vec3 = new Vec3(this.getX(), d0, this.getZ()); } this.dismountTo(vec3.x, vec3.y, vec3.z); } if (entity instanceof LivingEntity livingentity) { for (MobEffectInstance mobeffectinstance : livingentity.getActiveEffects()) { connection.send(new ClientboundRemoveMobEffectPacket(entity.getId(), mobeffectinstance.getEffect())); } } } } } ); } }