SuperLeadRope/src/main/java/top/r3944realms/superleadrope/compat/WayStoneCompat.java
3944Realms 3a519afad2 更新版本 v1.0.0 -> v1.1.0
添加了拴绳实体
新增新的附魔
调整拴绳数据cap实现
修改配置
删除无用代码
更新代码版权声明
优化import
2026-02-03 11:46:28 +08:00

185 lines
8.9 KiB
Java

/*
* Super Lead rope mod
* Copyright (C) 2026 R3944Realms
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package top.r3944realms.superleadrope.compat;
import com.ibm.icu.impl.Pair;
import net.blay09.mods.waystones.api.WaystoneTeleportEvent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.ModList;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.superleadrope.api.event.SuperLeadRopeEvent;
import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo;
import top.r3944realms.superleadrope.api.type.util.ILeashHelper;
import top.r3944realms.superleadrope.api.workspace.Services;
import top.r3944realms.superleadrope.content.gamerule.server.TeleportWithLeashedEntities;
import top.r3944realms.superleadrope.core.leash.LeashSyncManager;
import top.r3944realms.superleadrope.core.register.SLPGameruleRegistry;
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI;
import top.r3944realms.superleadrope.util.entity.TeleportUtil;
import top.r3944realms.superleadrope.util.model.RidingRelationship;
import top.r3944realms.superleadrope.util.riding.RidingApplier;
import top.r3944realms.superleadrope.util.riding.RidingDismounts;
import top.r3944realms.superleadrope.util.riding.RidingFinder;
import top.r3944realms.superleadrope.util.riding.RidingSaver;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
/**
* The type Way stone compat.
*/
public class WayStoneCompat {
/**
* The constant isModLoaded.
*/
public final static boolean isModLoaded = ModList.get().isLoaded("waystones");
/**
* The constant tempLeashMap.
*/
public final static Map<UUID, Set<Pair<Entity, OriginalState>>> tempLeashMap = new ConcurrentHashMap<>();
/**
* The constant uuidMap.
*/
public final static Map<UUID, UUID> uuidMap = new ConcurrentHashMap<>();
/**
* The type Original state.
*/
public record OriginalState(Pose pose, boolean isSprinting, float yaw, float pitch, Vec3 deltaMovement, LeashInfo leashInfo, RidingRelationship ridingRelationship) {}
/**
* Init.
*/
public static void init() {
if (isModLoaded) {
MinecraftForge.EVENT_BUS.addListener(WayStoneCompat::onWayStoneTeleport$Pre);
MinecraftForge.EVENT_BUS.addListener(WayStoneCompat::onWayStoneTeleport$Post);
}
}
/**
* On way stone teleport pre.
*
* @param event the event
*/
public static void onWayStoneTeleport$Pre(WaystoneTeleportEvent.@NotNull Pre event) {
Entity telEntity = event.getContext().getEntity();
ILeashHelper.IHolder holderHelper = Services.WORK_SPACE.getLeashHelper().getHolderHelper(telEntity);
Set<Entity> allLeashedEntities = holderHelper.getAllLeashedEntities();
if(!SLPGameruleRegistry.getGameruleBoolValue(telEntity.level(), TeleportWithLeashedEntities.ID)) {
holderHelper.getAllLeashedEntities();
return;
}
ServerLevel level = event.getContext().getDestination().getLevel();
Vec3 destination = event.getContext().getDestination().getLocation();
Set<Pair<Entity, OriginalState>> set = new HashSet<>();
for (Entity beLeashedEntity : allLeashedEntities) {
// --- 保存状态快照 ---
if (MinecraftForge.EVENT_BUS.post(new SuperLeadRopeEvent.teleportWithHolder(beLeashedEntity, telEntity, beLeashedEntity.level(), level, beLeashedEntity.position(), destination)))
continue;
Pose originalPose = beLeashedEntity.getPose();
boolean originalIsSprinting = beLeashedEntity.isSprinting();
float originalYaw = beLeashedEntity.getYRot();
float originalPitch = beLeashedEntity.getXRot();
Vec3 originalDeltaMovement = beLeashedEntity.getDeltaMovement();
AtomicReference<LeashInfo> originalLeashInfo = new AtomicReference<>();
LeashDataInnerAPI.getLeashData(beLeashedEntity).ifPresent(data -> {
originalLeashInfo.set(data.getLeashInfo(telEntity).orElse(null));
data.removeLeash(telEntity);
});
// --- 保存骑乘关系(可修改列表) ---
RidingRelationship originalRidingRelationship = RidingSaver.save(beLeashedEntity, true);
// --- 解除骑乘 ---
List<Entity> allPassengers = RidingFinder.getEntityFromRidingShip(originalRidingRelationship, level::getEntity);
RidingDismounts.dismountEntities(allPassengers);
set.add(Pair.of(beLeashedEntity, new OriginalState(
originalPose,
originalIsSprinting,
originalYaw,
originalPitch,
originalDeltaMovement,
originalLeashInfo.get(),
originalRidingRelationship
)
)
);
}
tempLeashMap.put(telEntity.getUUID(), set);
}
/**
* On way stone teleport post.
*
* @param event the event
*/
public static void onWayStoneTeleport$Post(WaystoneTeleportEvent.@NotNull Post event) {
Entity telEntity = event.getContext().getEntity();
ServerLevel serverLevel = event.getContext().getDestination().getLevel();
Vec3 destination = event.getContext().getDestination().getLocation();
Set<Pair<Entity, OriginalState>> set = tempLeashMap.get(telEntity.getUUID());
Set<UUID> shouldBeRemoved = new HashSet<>();
if (set != null) {
HashSet<Pair<Entity, OriginalState>> newSet = new HashSet<>();
// --- 传送实体及乘客 ---
for (Pair<Entity, OriginalState> entityPair : set) {
Entity beLeashedEntity = entityPair.first;
Entity newEntity = TeleportUtil.teleportEntity(beLeashedEntity, serverLevel, destination, beLeashedEntity.getDirection());
if (!beLeashedEntity.getUUID().equals(newEntity.getUUID())){
uuidMap.put(beLeashedEntity.getUUID(), newEntity.getUUID());
}
newSet.add(Pair.of(newEntity, entityPair.second));
}
for (Pair<Entity, OriginalState> entityPair : newSet) {
// --- 恢复状态 ---
Entity beLeashedEntity = entityPair.first;
OriginalState originalState = entityPair.second;
LeashStateInnerAPI.getLeashState(beLeashedEntity).ifPresent(LeashSyncManager.State::track);
LeashDataInnerAPI.getLeashData(beLeashedEntity).ifPresent(LeashSyncManager.Data::track);
beLeashedEntity.setDeltaMovement(originalState.deltaMovement);
beLeashedEntity.setPose(originalState.pose);
beLeashedEntity.setSprinting(originalState.isSprinting);
// --- 将holder替换 ---
LeashInfo leashInfo = Optional.ofNullable(originalState.leashInfo)
.orElse(LeashInfo.EMPTY);
if (leashInfo.holderUUIDOpt().isPresent() && uuidMap.containsKey(leashInfo.holderUUIDOpt().get())) {
leashInfo.transferHolder(beLeashedEntity);
shouldBeRemoved.add(leashInfo.holderUUIDOpt().get());
}
LeashDataInnerAPI.LeashOperations.attachWithInfo(beLeashedEntity, telEntity, leashInfo);
// --- 重新应用骑乘关系,仅保留白名单根载具 ---
uuidMap.forEach((oldUUID, newUUID) -> {
int andReplaceAll = originalState.ridingRelationship.findAndReplaceAll(oldUUID, newUUID);
if (andReplaceAll != 0) shouldBeRemoved.add(oldUUID);
});
RidingRelationship filteredRelationship = RidingSaver.filterByWhitelistRoot(originalState.ridingRelationship);
RidingApplier.applyRidingRelationship(filteredRelationship, serverLevel::getEntity);
}
shouldBeRemoved.forEach(uuidMap::remove);
tempLeashMap.remove(telEntity.getUUID());
}
}
}