diff --git a/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java index 32841385..bd8fe824 100644 --- a/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java +++ b/src/main/java/ru/betterend/mixin/common/EndPortalFeatureMixin.java @@ -5,9 +5,11 @@ import java.util.Random; 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.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Heightmap.Type; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; @@ -20,6 +22,13 @@ public class EndPortalFeatureMixin { private void bePortalGenerate(StructureWorldAccess structureWorldAccess, ChunkGenerator chunkGenerator, Random random, BlockPos blockPos, DefaultFeatureConfig defaultFeatureConfig, CallbackInfoReturnable info) { if (!GeneratorOptions.hasPortal()) { info.setReturnValue(false); + 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()); + } } diff --git a/src/main/java/ru/betterend/mixin/common/EndSpikeFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/EndSpikeFeatureMixin.java index 662e3ef4..220a93c3 100644 --- a/src/main/java/ru/betterend/mixin/common/EndSpikeFeatureMixin.java +++ b/src/main/java/ru/betterend/mixin/common/EndSpikeFeatureMixin.java @@ -5,13 +5,24 @@ import java.util.Random; 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.CallbackInfoReturnable; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.PaneBlock; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.Heightmap.Type; +import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.EndSpikeFeature; import net.minecraft.world.gen.feature.EndSpikeFeatureConfig; +import ru.betterend.util.BlocksHelper; import ru.betterend.world.generator.GeneratorOptions; @Mixin(EndSpikeFeature.class) @@ -22,4 +33,62 @@ public class EndSpikeFeatureMixin { info.setReturnValue(false); } } + + @Inject(method = "generateSpike", at = @At("HEAD"), cancellable = true) + private void be_generateSpike(ServerWorldAccess world, Random random, EndSpikeFeatureConfig config, EndSpikeFeature.Spike spike, CallbackInfo info) { + int x = spike.getCenterX(); + int z = spike.getCenterZ(); + int radius = spike.getRadius(); + int minY = world.getChunk(spike.getCenterX() >> 4, spike.getCenterZ() >> 4).sampleHeightmap(Type.WORLD_SURFACE, spike.getCenterX() & 15, spike.getCenterZ() & 15) - 15; + int maxY = minY + spike.getHeight() - 50; + + int r2 = radius * radius + 1; + Mutable mut = new Mutable(); + for (int px = -radius; px <= radius; px++) { + mut.setX(x + px); + int x2 = px * px; + for (int pz = -radius; pz <= radius; pz++) { + mut.setZ(z + pz); + int z2 = pz * pz; + if (x2 + z2 <= r2) { + for (int py = minY; py < maxY; py++) { + mut.setY(py); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.OBSIDIAN); + } + } + } + } + } + mut.setX(x); + mut.setZ(z); + mut.setY(maxY); + BlocksHelper.setWithoutUpdate(world, mut, Blocks.BEDROCK); + + EndCrystalEntity crystal = EntityType.END_CRYSTAL.create(world.toServerWorld()); + crystal.setBeamTarget(config.getPos()); + crystal.setInvulnerable(config.isCrystalInvulnerable()); + crystal.refreshPositionAndAngles(x + 0.5D, maxY + 1, z + 0.5D, random.nextFloat() * 360.0F, 0.0F); + world.spawnEntity(crystal); + + if (spike.isGuarded()) { + for (int px = -2; px <= 2; ++px) { + boolean bl = MathHelper.abs(px) == 2; + for (int pz = -2; pz <= 2; ++pz) { + boolean bl2 = MathHelper.abs(pz) == 2; + for (int py = 0; py <= 3; ++py) { + boolean bl3 = py == 3; + if (bl || bl2 || bl3) { + boolean bl4 = px == -2 || px == 2 || bl3; + boolean bl5 = pz == -2 || pz == 2 || bl3; + BlockState blockState = (BlockState) ((BlockState) ((BlockState) ((BlockState) Blocks.IRON_BARS.getDefaultState().with(PaneBlock.NORTH, bl4 && pz != -2)).with(PaneBlock.SOUTH, bl4 && pz != 2)).with(PaneBlock.WEST, bl5 && px != -2)).with(PaneBlock.EAST, bl5 && px != 2); + BlocksHelper.setWithoutUpdate(world, mut.set(spike.getCenterX() + px, maxY + py, spike.getCenterZ() + pz), blockState); + } + } + } + } + } + + info.cancel(); + } }