diff --git a/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java index bd8fe824..fc69f5a8 100644 --- a/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java +++ b/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java @@ -2,33 +2,71 @@ package ru.betterend.mixin.common; import java.util.Random; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import net.minecraft.nbt.NbtHelper; +import net.minecraft.structure.Structure; +import net.minecraft.structure.StructurePlacementData; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.Heightmap.Type; import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.Heightmap.Type; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; import net.minecraft.world.gen.feature.EndPortalFeature; +import ru.betterend.BetterEnd; +import ru.betterend.util.StructureHelper; +import ru.betterend.util.WorldDataUtil; import ru.betterend.world.generator.GeneratorOptions; @Mixin(EndPortalFeature.class) public class EndPortalFeatureMixin { + @Final + @Shadow + private boolean open; + @Inject(method = "generate", at = @At("HEAD"), cancellable = true) - private void bePortalGenerate(StructureWorldAccess structureWorldAccess, ChunkGenerator chunkGenerator, Random random, BlockPos blockPos, DefaultFeatureConfig defaultFeatureConfig, CallbackInfoReturnable info) { + private void bePortalGenerate(StructureWorldAccess world, ChunkGenerator generator, Random random, BlockPos blockPos, DefaultFeatureConfig config, CallbackInfoReturnable info) { if (!GeneratorOptions.hasPortal()) { info.setReturnValue(false); info.cancel(); } + else if (GeneratorOptions.replacePortal()) { + blockPos = be_updatePos(blockPos, world); + Structure structure = StructureHelper.readStructure(BetterEnd.makeID(open ? "portal/end_portal_active" : "portal/end_portal_inactive")); + BlockPos size = structure.getSize(); + blockPos = blockPos.add(-(size.getX() >> 1), -3, -(size.getZ() >> 1)); + structure.place(world, blockPos, new StructurePlacementData(), random); + info.setReturnValue(true); + info.cancel(); + } } @ModifyVariable(method = "generate", ordinal = 0, at = @At("HEAD")) - private BlockPos be_setPosOnGround(BlockPos blockPos, StructureWorldAccess structureWorldAccess) { - int y = structureWorldAccess.getChunk(blockPos).sampleHeightmap(Type.WORLD_SURFACE, blockPos.getX() & 15, blockPos.getZ() & 15); - return new BlockPos(blockPos.getX(), y, blockPos.getZ()); + private BlockPos be_setPosOnGround(BlockPos blockPos, StructureWorldAccess world) { + return be_updatePos(blockPos, world); + } + + private BlockPos be_updatePos(BlockPos blockPos, StructureWorldAccess world) { + if (GeneratorOptions.useNewGenerator()) { + BlockPos pos = GeneratorOptions.getPortalPos(); + if (pos.equals(BlockPos.ORIGIN)) { + int y = world.getChunk(blockPos).sampleHeightmap(Type.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()); + if (y < 1) { + y = 65; + } + pos = new BlockPos(pos.getX(), y, pos.getZ()); + GeneratorOptions.setPortalPos(pos); + WorldDataUtil.getRootTag().put("portal", NbtHelper.fromBlockPos(pos)); + WorldDataUtil.saveFile(); + } + return pos; + } + return blockPos; } } diff --git a/src/main/java/ru/betterend/mixin/common/ServerWorldMixin.java b/src/main/java/ru/betterend/mixin/common/ServerWorldMixin.java index 35a1f5e2..afc357d1 100644 --- a/src/main/java/ru/betterend/mixin/common/ServerWorldMixin.java +++ b/src/main/java/ru/betterend/mixin/common/ServerWorldMixin.java @@ -1,7 +1,6 @@ package ru.betterend.mixin.common; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.concurrent.Executor; @@ -14,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtHelper; import net.minecraft.server.MinecraftServer; import net.minecraft.server.WorldGenerationProgressListener; import net.minecraft.server.world.ServerWorld; @@ -28,6 +27,7 @@ import net.minecraft.world.level.ServerWorldProperties; import net.minecraft.world.level.storage.LevelStorage; import ru.betterend.BetterEnd; import ru.betterend.util.DataFixerUtil; +import ru.betterend.util.WorldDataUtil; import ru.betterend.world.generator.GeneratorOptions; @Mixin(ServerWorld.class) @@ -37,26 +37,17 @@ public class ServerWorldMixin { File beData = new File(FabricLoader.getInstance().getGameDir().getParent().toString(), "saves/" + properties.getLevelName() + "/betterend_data.nbt"); ModMetadata meta = FabricLoader.getInstance().getModContainer(BetterEnd.MOD_ID).get().getMetadata(); String version = BetterEnd.isDevEnvironment() ? "development" : meta.getVersion().toString(); - boolean fix = false; - if (beData.exists()) { - CompoundTag root; - try { - root = NbtIo.read(beData); - } - catch (IOException e) { - BetterEnd.LOGGER.error("World data loading failed", e); - return; - } - String dataVersion = root.getString("version"); - fix = !dataVersion.equals(version); - } - else { - fix = true; - } + + WorldDataUtil.load(beData); + CompoundTag root = WorldDataUtil.getRootTag(); + String dataVersion = root.getString("version"); + GeneratorOptions.setPortalPos(NbtHelper.toBlockPos(root.getCompound("portal"))); + boolean fix = !dataVersion.equals(version); if (fix) { DataFixerUtil.fixData(beData.getParentFile()); - be_writeDataFile(beData, version); + root.putString("version", version); + WorldDataUtil.saveFile(); } } @@ -69,15 +60,4 @@ public class ServerWorldMixin { } } } - - private void be_writeDataFile(File file, String version) { - CompoundTag root = new CompoundTag(); - root.putString("version", version); - try { - NbtIo.write(root, file); - } - catch (IOException e) { - BetterEnd.LOGGER.error("World data saving failed", e); - } - } } diff --git a/src/main/java/ru/betterend/util/WorldDataUtil.java b/src/main/java/ru/betterend/util/WorldDataUtil.java new file mode 100644 index 00000000..4ba51df2 --- /dev/null +++ b/src/main/java/ru/betterend/util/WorldDataUtil.java @@ -0,0 +1,41 @@ +package ru.betterend.util; + +import java.io.File; +import java.io.IOException; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import ru.betterend.BetterEnd; + +public class WorldDataUtil { + private static CompoundTag root; + private static File saveFile; + + public static void load(File file) { + saveFile = file; + if (file.exists()) { + try { + root = NbtIo.read(file); + } + catch (IOException e) { + BetterEnd.LOGGER.error("World data loading failed", e); + root = new CompoundTag(); + } + return; + } + root = new CompoundTag(); + } + + public static CompoundTag getRootTag() { + return root; + } + + public static void saveFile() { + try { + NbtIo.write(root, saveFile); + } + catch (IOException e) { + BetterEnd.LOGGER.error("World data saving failed", e); + } + } +} diff --git a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java index 7e5cc0ee..baee736f 100644 --- a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java +++ b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java @@ -23,6 +23,8 @@ public class GeneratorOptions { public static LayerOptions smallOptions; private static boolean changeSpawn; private static BlockPos spawn; + private static BlockPos portal = BlockPos.ORIGIN; + private static boolean replacePortal; public static void init() { biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 256); @@ -47,6 +49,7 @@ public class GeneratorOptions { Configs.GENERATOR_CONFIG.getInt("spawn.point", "y", 65), Configs.GENERATOR_CONFIG.getInt("spawn.point", "z", 0) ); + replacePortal = Configs.GENERATOR_CONFIG.getBooleanRoot("customEndPortal", true); } public static int getBiomeSizeLand() { @@ -108,4 +111,16 @@ public class GeneratorOptions { public static BlockPos getSpawn() { return spawn; } + + public static BlockPos getPortalPos() { + return portal; + } + + public static void setPortalPos(BlockPos portal) { + GeneratorOptions.portal = portal; + } + + public static boolean replacePortal() { + return replacePortal; + } } diff --git a/src/main/resources/data/betterend/structures/portal/end_portal_active.nbt b/src/main/resources/data/betterend/structures/portal/end_portal_active.nbt new file mode 100644 index 00000000..27ef1e47 Binary files /dev/null and b/src/main/resources/data/betterend/structures/portal/end_portal_active.nbt differ diff --git a/src/main/resources/data/betterend/structures/portal/end_portal_inactive.nbt b/src/main/resources/data/betterend/structures/portal/end_portal_inactive.nbt new file mode 100644 index 00000000..30047c92 Binary files /dev/null and b/src/main/resources/data/betterend/structures/portal/end_portal_inactive.nbt differ