mirror of
https://github.com/Mr-dayhappy/Minecraft-place-mod.git
synced 2026-10-23 01:53:39 +08:00
原版 PlaceCommand.placeStructure 只调 StructureStart.placeInChunk 摆放方块,从不把 StructureStart 注册进 StructureManager / 区块 StructureAccess,导致结构重启丢失、专属刷怪规则不激活。 新增 PlaceCommandMixin,在 placeStructure 返回前补做自然生成的三步:1) setStartForStructure 把 start 存进所在区块;2) createReferences 写 17x17 邻居引用;3) markUnsaved 强制存盘。全程 try-catch 兜底,注册失败不影响命令返回。 项目骨架参照 CarpetSLSAddition:Loom 1.18-SNAPSHOT + Gradle 9.7.1 + Java 25 + official 映射。
88 lines
3.9 KiB
Java
88 lines
3.9 KiB
Java
package com.github.axtps.placemod.mixin;
|
||
|
||
import com.github.axtps.placemod.PlaceMod;
|
||
import net.minecraft.core.SectionPos;
|
||
import net.minecraft.server.commands.PlaceCommand;
|
||
import net.minecraft.server.level.ServerLevel;
|
||
import net.minecraft.world.level.ChunkPos;
|
||
import net.minecraft.world.level.StructureManager;
|
||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||
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;
|
||
|
||
/**
|
||
* 让 /place structure 生成的结构"跟自然生成一样"。
|
||
*
|
||
* 原版 PlaceCommand.placeStructure 只调了 StructureStart.placeInChunk 摆放方块,
|
||
* 从不把 StructureStart 注册进 StructureManager / 区块 StructureAccess。
|
||
* 结果:结构不进 StructureManager、不写区块 NBT 引用 → 重启丢失、专属刷怪规则不激活。
|
||
*
|
||
* 本 Mixin 在 placeStructure 返回前,补做自然生成的注册步骤:
|
||
* 1. 对结构所在区块 setStartForStructure,把 start 存进区块;
|
||
* 2. 调 ChunkGenerator.createReferences 写周围区块引用(跟自然生成同款逻辑);
|
||
* 3. markUnsaved 标记涉及的区块,强制存盘。
|
||
*/
|
||
@Mixin(PlaceCommand.class)
|
||
public class PlaceCommandMixin {
|
||
|
||
@Inject(method = "placeStructure", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||
private static void placemod$registerStructure(net.minecraft.commands.CommandSourceStack source,
|
||
net.minecraft.core.Holder.Reference<Structure> structureHolder,
|
||
net.minecraft.core.BlockPos pos,
|
||
CallbackInfo ci,
|
||
ServerLevel level,
|
||
Structure structure,
|
||
ChunkGenerator generator,
|
||
StructureStart start) {
|
||
if (start == null || !start.isValid()) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
StructureManager structureManager = level.structureManager();
|
||
BoundingBox box = start.getBoundingBox();
|
||
|
||
// 结构包围盒覆盖的区块范围
|
||
ChunkPos minChunk = new ChunkPos(
|
||
SectionPos.blockToSectionCoord(box.minX()),
|
||
SectionPos.blockToSectionCoord(box.minZ()));
|
||
ChunkPos maxChunk = new ChunkPos(
|
||
SectionPos.blockToSectionCoord(box.maxX()),
|
||
SectionPos.blockToSectionCoord(box.maxZ()));
|
||
|
||
// 1) 把 StructureStart 存进它自己所在的区块
|
||
// (自然生成在 ChunkGenerator.createStructures 里做)
|
||
ChunkPos startChunk = start.getChunkPos();
|
||
ChunkAccess startChunkAccess = level.getChunk(startChunk.x(), startChunk.z());
|
||
structureManager.setStartForStructure(
|
||
SectionPos.bottomOf(startChunkAccess), structure, start, startChunkAccess);
|
||
startChunkAccess.markUnsaved();
|
||
|
||
// 2) 引用写入:对涉及的每个区块调 createReferences,
|
||
// 它内部会扫 17x17 邻居,把相交的 StructureStart 引用写进区块。
|
||
// 跟自然生成用的是同一个方法,保证"完全一样"。
|
||
ChunkPos.rangeClosed(minChunk, maxChunk).forEach(cp -> {
|
||
ChunkAccess chunk = level.getChunk(cp.x(), cp.z());
|
||
try {
|
||
generator.createReferences(level, structureManager, chunk);
|
||
chunk.markUnsaved();
|
||
} catch (Exception e) {
|
||
PlaceMod.LOGGER.error("[place-mod] createReferences 失败 @ {}: {}", cp, e.toString());
|
||
}
|
||
});
|
||
|
||
PlaceMod.LOGGER.info("[place-mod] 已为结构 {} 补注册 StructureStart @ {}",
|
||
structure, startChunk);
|
||
} catch (Throwable t) {
|
||
// 注册失败不能影响命令本身的成功返回
|
||
PlaceMod.LOGGER.error("[place-mod] 补注册结构时出错(已忽略): ", t);
|
||
}
|
||
}
|
||
} |