diff --git a/src/main/java/ru/betterend/blocks/EndPortalBlock.java b/src/main/java/ru/betterend/blocks/EndPortalBlock.java index 1bc5bfd9..69153e55 100644 --- a/src/main/java/ru/betterend/blocks/EndPortalBlock.java +++ b/src/main/java/ru/betterend/blocks/EndPortalBlock.java @@ -5,20 +5,29 @@ import java.util.Random; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.NetherPortalBlock; import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.registry.Registry; import net.minecraft.world.Heightmap; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.feature.ConfiguredFeatures; import ru.betterend.client.ERenderLayer; import ru.betterend.client.IRenderTypeable; +import ru.betterend.interfaces.TeleportingEntity; +import ru.betterend.registry.BlockTagRegistry; +import ru.betterend.registry.FeatureRegistry; import ru.betterend.registry.ParticleRegistry; public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable { @@ -58,7 +67,17 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable @Override public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { - BlockPos exitPos = this.findExitPos(world, pos); + if (world instanceof ServerWorld && entity instanceof LivingEntity && !entity.hasVehicle() && !entity.hasPassengers() && entity.canUsePortals()) { + TeleportingEntity teleEntity = TeleportingEntity.class.cast(entity); + if (teleEntity.hasCooldown()) return; + teleEntity.beSetCooldown(500); + boolean isOverworld = world.getRegistryKey().equals(World.OVERWORLD); + ServerWorld destination = ((ServerWorld) world).getServer().getWorld(isOverworld ? World.END : World.OVERWORLD); + BlockPos exitPos = this.findExitPos(destination, pos, entity); + teleEntity.beSetExitPos(exitPos); + entity.moveToWorld(destination); + teleEntity.beSetExitPos(null); + } } @Override @@ -66,16 +85,96 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable return ERenderLayer.TRANSLUCENT; } - private BlockPos findExitPos(World world, BlockPos pos) { + private BlockPos findExitPos(ServerWorld world, BlockPos pos, Entity entity) { + Registry registry = world.getRegistryManager().getDimensionTypes(); + double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale(); + int topY; + BlockPos.Mutable basePos; if (world.getRegistryKey().equals(World.OVERWORLD)) { - BlockPos basePos = pos.mutableCopy().set(pos.getX() * 8, pos.getY() * 8, pos.getZ() * 8); - int height = world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, basePos.getX(), basePos.getZ()); - BlockPos.iterate(basePos.add(-16, -pos.getY() + 1, -16), basePos.add(16, height, 16)).forEach(position -> { - - }); + basePos = pos.mutableCopy().set(pos.getX() / mult, pos.getY(), pos.getZ() / mult); + topY = world.getTopY(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ()); } else { - + basePos = pos.mutableCopy().set(pos.getX() * mult, pos.getY(), pos.getZ() * mult); + topY = world.getHeight(); } - return pos; + BlockPos top = basePos.mutableCopy().set(basePos.getX() + 32, topY, basePos.getZ() + 32); + BlockPos.Mutable bottom = basePos.mutableCopy().set(basePos.getX() - 32, 5, basePos.getZ() - 32); + for(BlockPos position : BlockPos.iterate(bottom, top)) { + BlockState state = world.getBlockState(position); + if(state.isOf(this)) { + if (state.get(AXIS).equals(Direction.Axis.X)) { + return position.add(1, 0, 0); + } else { + return position.add(0, 0, 1); + } + } + } + bottom.setY(basePos.getY()); + Direction.Axis axis = entity.getMovementDirection().getAxis(); + if (checkIsAreaValid(world, bottom)) { + generatePortalFrame(world, bottom, axis, true); + if (axis.equals(Direction.Axis.X)) { + return bottom.add(1, 1, 0); + } else { + return bottom.add(0, 1, 1); + } + } else { + if (bottom.getY() > top.getY()) { + BlockPos buff = bottom; + bottom = top.mutableCopy(); + top = buff; + } + for(BlockPos position : BlockPos.iterate(bottom, top)) { + if (checkIsAreaValid(world, position)) { + generatePortalFrame(world, position, axis, true); + if (axis.equals(Direction.Axis.X)) { + return position.add(1, 1, 0); + } else { + return position.add(0, 1, 1); + } + } + } + } + if (world.getRegistryKey().equals(World.END)) { + ConfiguredFeatures.END_ISLAND.generate(world, world.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos); + } else { + basePos.setY(topY); + } + generatePortalFrame(world, basePos, axis, true); + if (axis.equals(Direction.Axis.X)) { + return basePos.add(1, 1, 0); + } else { + return basePos.add(0, 1, 1); + } + } + + private boolean checkIsAreaValid(World world, BlockPos pos) { + BlockPos bottomCorner = pos.add(-1, 0, -1); + BlockPos topCorner = bottomCorner.add(4, 4, 1); + int airBlocks = 0; + boolean free = true; + for (BlockPos position : BlockPos.iterate(bottomCorner, topCorner)) { + BlockState state = world.getBlockState(position); + if (state.isAir()) airBlocks++; + if (world.getRegistryKey().equals(World.END)) { + free &= state.isAir() || BlockTagRegistry.validGenBlock(state); + } else { + BlockState surfaceBlock = world.getBiome(pos).getGenerationSettings().getSurfaceConfig().getTopMaterial(); + free &= this.validBlock(state, surfaceBlock.getBlock()); + } + } + return free && airBlocks == 48; + } + + private boolean validBlock(BlockState state, Block surfaceBlock) { + return state.isAir() || + state.isOf(surfaceBlock) || + state.isOf(Blocks.STONE) || + state.isOf(Blocks.SAND) || + state.isOf(Blocks.GRAVEL); + } + + public static void generatePortalFrame(ServerWorld world, BlockPos pos, Direction.Axis axis, boolean active) { + FeatureRegistry.END_PORTAL.configure(axis, active).getFeatureConfigured().generate(world, world.getChunkManager().getChunkGenerator(), new Random(), pos); } } diff --git a/src/main/java/ru/betterend/blocks/RunedFlavolite.java b/src/main/java/ru/betterend/blocks/RunedFlavolite.java index 2debd147..241cb382 100644 --- a/src/main/java/ru/betterend/blocks/RunedFlavolite.java +++ b/src/main/java/ru/betterend/blocks/RunedFlavolite.java @@ -1,12 +1,18 @@ package ru.betterend.blocks; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.StateManager; import net.minecraft.state.property.BooleanProperty; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + import ru.betterend.blocks.basis.BlockBase; import ru.betterend.registry.BlockRegistry; +import ru.betterend.util.BlocksHelper; public class RunedFlavolite extends BlockBase { public static final BooleanProperty ACTIVATED = BooleanProperty.of("active"); @@ -22,4 +28,20 @@ public class RunedFlavolite extends BlockBase { protected void appendProperties(StateManager.Builder stateManager) { stateManager.add(ACTIVATED); } + + @Override + public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + super.onBreak(world, pos, state, player); + if(state.get(ACTIVATED)) { + for (BlockPos position : BlockPos.iterate(pos.add(-3, -4, -3), pos.add(3, 4, 3))) { + if (position.equals(pos)) continue; + BlockState posState = world.getBlockState(position); + if (posState.getBlock() instanceof RunedFlavolite) { + BlocksHelper.setWithoutUpdate(world, position, posState.with(ACTIVATED, false)); + } else if (posState.isOf(BlockRegistry.END_PORTAL_BLOCK)) { + world.removeBlock(position, false); + } + } + } + } } diff --git a/src/main/java/ru/betterend/interfaces/TeleportingEntity.java b/src/main/java/ru/betterend/interfaces/TeleportingEntity.java new file mode 100644 index 00000000..c46a2c6a --- /dev/null +++ b/src/main/java/ru/betterend/interfaces/TeleportingEntity.java @@ -0,0 +1,14 @@ +package ru.betterend.interfaces; + +import net.minecraft.util.math.BlockPos; + +public interface TeleportingEntity { + public abstract long beGetCooldown(); + public abstract void beSetCooldown(long time); + public abstract void beSetExitPos(BlockPos pos); + public abstract BlockPos beGetExitPos(); + + default boolean hasCooldown() { + return this.beGetCooldown() > 0; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/EntityMixin.java b/src/main/java/ru/betterend/mixin/common/EntityMixin.java new file mode 100644 index 00000000..023a58fa --- /dev/null +++ b/src/main/java/ru/betterend/mixin/common/EntityMixin.java @@ -0,0 +1,116 @@ +package ru.betterend.mixin.common; + +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.TeleportTarget; +import net.minecraft.world.World; +import ru.betterend.interfaces.TeleportingEntity; + +@Mixin(Entity.class) +public abstract class EntityMixin implements TeleportingEntity { + + private BlockPos beExitPos; + private long beCooldown; + + @Shadow + public float yaw; + @Shadow + public float pitch; + @Shadow + public boolean removed; + @Shadow + public World world; + + @Final + @Shadow + public abstract void detach(); + + @Shadow + public abstract Vec3d getVelocity(); + + @Shadow + public abstract EntityType getType(); + + @Shadow + public abstract void copyFrom(Entity original); + + @Shadow + public abstract Entity moveToWorld(ServerWorld destination); + + @Shadow + protected abstract TeleportTarget getTeleportTarget(ServerWorld destination); + + @Inject(method = "moveToWorld", at = @At("HEAD"), cancellable = true) + public void moveToWorld(ServerWorld destination, CallbackInfoReturnable info) { + if (!removed && beExitPos != null && world instanceof ServerWorld) { + this.detach(); + this.world.getProfiler().push("changeDimension"); + this.world.getProfiler().push("reposition"); + TeleportTarget teleportTarget = this.getTeleportTarget(destination); + if (teleportTarget != null) { + this.world.getProfiler().swap("reloading"); + Entity entity = this.getType().create(destination); + if (entity != null) { + entity.copyFrom(Entity.class.cast(this)); + entity.refreshPositionAndAngles(teleportTarget.position.x, teleportTarget.position.y, teleportTarget.position.z, teleportTarget.yaw, entity.pitch); + entity.setVelocity(teleportTarget.velocity); + destination.onDimensionChanged(entity); + } + this.removed = true; + this.world.getProfiler().pop(); + ((ServerWorld) this.world).resetIdleTimeout(); + destination.resetIdleTimeout(); + this.world.getProfiler().pop(); + this.beExitPos = null; + info.setReturnValue(entity); + info.cancel(); + } + } + } + + @Inject(method = "getTeleportTarget", at = @At("HEAD"), cancellable = true) + protected void getTeleportTarget(ServerWorld destination, CallbackInfoReturnable info) { + if (beExitPos != null) { + info.setReturnValue(new TeleportTarget(new Vec3d(beExitPos.getX() + 0.5D, beExitPos.getY(), beExitPos.getZ() + 0.5D), getVelocity(), yaw, pitch)); + info.cancel(); + } + } + + @Inject(method = "baseTick", at = @At("TAIL")) + public void baseTick(CallbackInfo info) { + if (hasCooldown()) { + this.beCooldown--; + } + } + + @Override + public long beGetCooldown() { + return this.beCooldown; + } + + @Override + public void beSetCooldown(long time) { + this.beCooldown = time; + } + + @Override + public void beSetExitPos(BlockPos pos) { + this.beExitPos = pos; + } + + @Override + public BlockPos beGetExitPos() { + return this.beExitPos; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/ServerPlayerEntityMixin.java b/src/main/java/ru/betterend/mixin/common/ServerPlayerEntityMixin.java new file mode 100644 index 00000000..9e8aa9b7 --- /dev/null +++ b/src/main/java/ru/betterend/mixin/common/ServerPlayerEntityMixin.java @@ -0,0 +1,143 @@ +package ru.betterend.mixin.common; + +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.mojang.authlib.GameProfile; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.s2c.play.DifficultyS2CPacket; +import net.minecraft.network.packet.s2c.play.EntityStatusEffectS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket; +import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.TeleportTarget; +import net.minecraft.world.World; +import net.minecraft.world.WorldProperties; +import net.minecraft.world.biome.source.BiomeAccess; + +import ru.betterend.interfaces.TeleportingEntity; + +@Mixin(ServerPlayerEntity.class) +public abstract class ServerPlayerEntityMixin extends PlayerEntity implements TeleportingEntity { + + private BlockPos beExitPos; + private long beCooldown; + + @Shadow + private float syncedHealth; + @Shadow + private int syncedExperience; + @Shadow + private int syncedFoodLevel; + @Shadow + private boolean inTeleportationState; + @Shadow + public ServerPlayNetworkHandler networkHandler; + @Final + @Shadow + public MinecraftServer server; + @Final + @Shadow + public ServerPlayerInteractionManager interactionManager; + + public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile profile) { + super(world, pos, yaw, profile); + } + + @Shadow + public abstract ServerWorld getServerWorld(); + + @Shadow + protected abstract void worldChanged(ServerWorld origin); + + @Inject(method = "moveToWorld", at = @At("HEAD"), cancellable = true) + public void moveToWorld(ServerWorld destination, CallbackInfoReturnable info) { + ServerWorld serverWorld = this.getServerWorld(); + RegistryKey registryKey = serverWorld.getRegistryKey(); + if (beExitPos != null && registryKey == World.END && destination.getRegistryKey() == World.OVERWORLD) { + this.inTeleportationState = true; + ServerPlayerEntity player = ServerPlayerEntity.class.cast(this); + WorldProperties worldProperties = destination.getLevelProperties(); + this.networkHandler.sendPacket(new PlayerRespawnS2CPacket(destination.getDimension(), destination.getRegistryKey(), BiomeAccess.hashSeed(destination.getSeed()), this.interactionManager.getGameMode(), this.interactionManager.getPreviousGameMode(), destination.isDebugWorld(), destination.isFlat(), true)); + this.networkHandler.sendPacket(new DifficultyS2CPacket(worldProperties.getDifficulty(), worldProperties.isDifficultyLocked())); + PlayerManager playerManager = this.server.getPlayerManager(); + playerManager.sendCommandTree(player); + serverWorld.removePlayer(player); + this.removed = false; + TeleportTarget teleportTarget = this.getTeleportTarget(destination); + if (teleportTarget != null) { + serverWorld.getProfiler().push("placing"); + this.setWorld(destination); + destination.onPlayerChangeDimension(player); + this.setRotation(teleportTarget.yaw, teleportTarget.pitch); + this.refreshPositionAfterTeleport(teleportTarget.position.x, teleportTarget.position.y, teleportTarget.position.z); + serverWorld.getProfiler().pop(); + this.worldChanged(serverWorld); + this.interactionManager.setWorld(destination); + this.networkHandler.sendPacket(new PlayerAbilitiesS2CPacket(this.abilities)); + playerManager.sendWorldInfo(player, destination); + playerManager.sendPlayerStatus(player); + this.getStatusEffects().forEach(statusEffectInstance -> { + this.networkHandler.sendPacket(new EntityStatusEffectS2CPacket(getEntityId(), statusEffectInstance)); + }); + this.networkHandler.sendPacket(new WorldEventS2CPacket(1032, BlockPos.ORIGIN, 0, false)); + this.syncedExperience = -1; + this.syncedHealth = -1.0F; + this.syncedFoodLevel = -1; + info.setReturnValue(player); + info.cancel(); + } + } + } + + @Inject(method = "getTeleportTarget", at = @At("HEAD"), cancellable = true) + protected void getTeleportTarget(ServerWorld destination, CallbackInfoReturnable info) { + if (beExitPos != null) { + info.setReturnValue(new TeleportTarget(new Vec3d(beExitPos.getX() + 0.5D, beExitPos.getY(), beExitPos.getZ() + 0.5D), getVelocity(), yaw, pitch)); + info.cancel(); + } + } + + @Inject(method = "tick", at = @At("TAIL")) + public void baseTick(CallbackInfo info) { + if (hasCooldown()) { + this.beCooldown--; + } + } + + @Override + public long beGetCooldown() { + return this.beCooldown; + } + + @Override + public void beSetCooldown(long time) { + this.beCooldown = time; + } + + @Override + public void beSetExitPos(BlockPos pos) { + this.beExitPos = pos; + } + + @Override + public BlockPos beGetExitPos() { + return this.beExitPos; + } +} diff --git a/src/main/java/ru/betterend/registry/BlockTagRegistry.java b/src/main/java/ru/betterend/registry/BlockTagRegistry.java index ca7d6ca8..30b8420d 100644 --- a/src/main/java/ru/betterend/registry/BlockTagRegistry.java +++ b/src/main/java/ru/betterend/registry/BlockTagRegistry.java @@ -2,6 +2,7 @@ package ru.betterend.registry; import net.fabricmc.fabric.api.tag.TagRegistry; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; import net.minecraft.tag.Tag; import net.minecraft.tag.Tag.Identified; import net.minecraft.util.registry.Registry; @@ -42,4 +43,8 @@ public class BlockTagRegistry { } }); } + + public static boolean validGenBlock(BlockState block) { + return block.isIn(END_GROUND) || block.isIn(GEN_TERRAIN); + } } diff --git a/src/main/java/ru/betterend/registry/FeatureRegistry.java b/src/main/java/ru/betterend/registry/FeatureRegistry.java index 5b23d807..c2aa73bc 100644 --- a/src/main/java/ru/betterend/registry/FeatureRegistry.java +++ b/src/main/java/ru/betterend/registry/FeatureRegistry.java @@ -8,14 +8,17 @@ import com.google.common.collect.Lists; import net.minecraft.util.Identifier; import net.minecraft.world.biome.Biome; import net.minecraft.world.gen.feature.ConfiguredFeature; +import ru.betterend.blocks.RunedFlavolite; import ru.betterend.world.features.BlueVineFeature; import ru.betterend.world.features.CavePlantFeature; +import ru.betterend.world.features.DefaultEndPortalFeature; import ru.betterend.world.features.DoublePlantFeature; import ru.betterend.world.features.EndFeature; import ru.betterend.world.features.EndLakeFeature; import ru.betterend.world.features.EndLilyFeature; import ru.betterend.world.features.EndLotusFeature; import ru.betterend.world.features.EndLotusLeafFeature; +import ru.betterend.world.features.EndPortalFeature; import ru.betterend.world.features.MossyGlowshroomFeature; import ru.betterend.world.features.PythadendronBushFeature; import ru.betterend.world.features.PythadendronTreeFeature; @@ -59,6 +62,10 @@ public class FeatureRegistry { public static final EndFeature VIOLECITE_LAYER = EndFeature.makeLayerFeature("violecite_layer", BlockRegistry.VIOLECITE, 15, 4, 96, 8); public static final EndFeature FLAVOLITE_LAYER = EndFeature.makeLayerFeature("flavolite_layer", BlockRegistry.FLAVOLITE, 12, 4, 96, 6); + // Other // + public static final EndPortalFeature END_PORTAL = new EndPortalFeature(new DefaultEndPortalFeature(), (RunedFlavolite) BlockRegistry.FLAVOLITE_RUNED); + public static final EndPortalFeature END_PORTAL_ETERNAL = new EndPortalFeature(new DefaultEndPortalFeature(), (RunedFlavolite) BlockRegistry.FLAVOLITE_RUNED_ETERNAL); + public static void registerBiomeFeatures(Identifier id, Biome biome, List>>> features) { addFeature(FLAVOLITE_LAYER, features); addFeature(ENDER_ORE, features); diff --git a/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java b/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java new file mode 100644 index 00000000..c568b376 --- /dev/null +++ b/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java @@ -0,0 +1,64 @@ +package ru.betterend.world.features; + +import java.util.Random; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.Feature; + +import ru.betterend.blocks.EndPortalBlock; +import ru.betterend.blocks.RunedFlavolite; +import ru.betterend.registry.BlockRegistry; +import ru.betterend.util.BlocksHelper; + +public class DefaultEndPortalFeature extends Feature { + + public DefaultEndPortalFeature() { + super(EndPortalFeatureConfig.CODEC); + } + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, + EndPortalFeatureConfig config) { + + BlockState portalFrame = config.frameBlock.getDefaultState().with(RunedFlavolite.ACTIVATED, config.activated); + BlockState portalBlock = BlockRegistry.END_PORTAL_BLOCK.getDefaultState().with(EndPortalBlock.AXIS, config.axis); + BlockPos bottomCorner = pos; + BlockPos topCorner; + if (config.axis.equals(Direction.Axis.X)) { + topCorner = bottomCorner.add(3, 4, 0); + } else { + topCorner = bottomCorner.add(0, 4, 3); + } + + for(BlockPos position : BlockPos.iterate(bottomCorner, topCorner)) { + if (position.equals(bottomCorner) || position.equals(topCorner) || + position.getX() == bottomCorner.getX() && position.getZ() == bottomCorner.getZ() || + position.getX() == topCorner.getX() && position.getZ() == topCorner.getZ()) { + + BlocksHelper.setWithoutUpdate(world, position, portalFrame); + } else if (config.axis.equals(Direction.Axis.X)) { + if (position.getZ() == bottomCorner.getZ() && position.getY() == bottomCorner.getY() || + position.getZ() == topCorner.getZ() && position.getY() == topCorner.getY()) { + + BlocksHelper.setWithoutUpdate(world, position, portalFrame); + } else if (config.activated) { + BlocksHelper.setWithoutUpdate(world, position, portalBlock); + } + } else { + if (position.getX() == bottomCorner.getX() && position.getY() == bottomCorner.getY() || + position.getX() == topCorner.getX() && position.getY() == topCorner.getY()) { + + BlocksHelper.setWithoutUpdate(world, position, portalFrame); + } else if (config.activated) { + BlocksHelper.setWithoutUpdate(world, position, portalBlock); + } + } + } + + return true; + } +} diff --git a/src/main/java/ru/betterend/world/features/DefaultFeature.java b/src/main/java/ru/betterend/world/features/DefaultFeature.java index 92621d42..ed56799c 100644 --- a/src/main/java/ru/betterend/world/features/DefaultFeature.java +++ b/src/main/java/ru/betterend/world/features/DefaultFeature.java @@ -26,8 +26,7 @@ public abstract class DefaultFeature extends Feature { } protected BlockPos getPosOnSurfaceRaycast(StructureWorldAccess world, BlockPos pos) { - int h = BlocksHelper.downRay(world, pos, 256); - return pos.down(h); + return this.getPosOnSurfaceRaycast(world, pos, 256); } protected BlockPos getPosOnSurfaceRaycast(StructureWorldAccess world, BlockPos pos, int dist) { diff --git a/src/main/java/ru/betterend/world/features/EndFeature.java b/src/main/java/ru/betterend/world/features/EndFeature.java index de94c8fd..672814d7 100644 --- a/src/main/java/ru/betterend/world/features/EndFeature.java +++ b/src/main/java/ru/betterend/world/features/EndFeature.java @@ -22,11 +22,11 @@ import ru.betterend.BetterEnd; import ru.betterend.blocks.complex.StoneMaterial; public class EndFeature { - private Feature feature; - private ConfiguredFeature featureConfigured; - private GenerationStep.Feature featureStep; + protected Feature feature; + protected ConfiguredFeature featureConfigured; + protected GenerationStep.Feature featureStep; - private EndFeature() {} + protected EndFeature() {} public EndFeature(String name, Feature feature, GenerationStep.Feature featureStep, ConfiguredFeature configuredFeature) { Identifier id = BetterEnd.makeID(name); diff --git a/src/main/java/ru/betterend/world/features/EndPortalFeature.java b/src/main/java/ru/betterend/world/features/EndPortalFeature.java index 2a6cb60a..dd192115 100644 --- a/src/main/java/ru/betterend/world/features/EndPortalFeature.java +++ b/src/main/java/ru/betterend/world/features/EndPortalFeature.java @@ -1,64 +1,22 @@ package ru.betterend.world.features; -import java.util.Random; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.feature.Feature; -import ru.betterend.blocks.EndPortalBlock; +import net.minecraft.world.gen.GenerationStep; + import ru.betterend.blocks.RunedFlavolite; -import ru.betterend.registry.BlockRegistry; -import ru.betterend.util.BlocksHelper; -public class EndPortalFeature extends Feature { - - public EndPortalFeature(Block frameBlock) { - super(EndPortalFeatureConfig.CODEC); +public class EndPortalFeature extends EndFeature { + + private final RunedFlavolite frameBlock; + + public EndPortalFeature(DefaultEndPortalFeature feature, RunedFlavolite frameBlock) { + this.feature = feature; + this.featureStep = GenerationStep.Feature.UNDERGROUND_STRUCTURES; + this.frameBlock = frameBlock; } - - @Override - public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, - EndPortalFeatureConfig config) { - - BlockState portalFrame = config.frameBlock.getDefaultState().with(RunedFlavolite.ACTIVATED, config.activated); - BlockState portalBlock = BlockRegistry.END_PORTAL_BLOCK.getDefaultState().with(EndPortalBlock.AXIS, config.axis); - BlockPos bottomCorner = pos; - BlockPos topCorner; - if (config.axis.equals(Direction.Axis.X)) { - topCorner = bottomCorner.add(0, 4, 3); - } else { - topCorner = bottomCorner.add(3, 4, 0); - } - - for(BlockPos position : BlockPos.iterate(bottomCorner, topCorner)) { - if (position.equals(bottomCorner) || position.equals(topCorner) || - position.getX() == bottomCorner.getX() && position.getZ() == bottomCorner.getZ() || - position.getX() == topCorner.getX() && position.getZ() == topCorner.getZ()) { - - BlocksHelper.setWithoutUpdate(world, position, portalFrame); - } else if (config.axis.equals(Direction.Axis.X)) { - if (position.getX() == bottomCorner.getX() && position.getY() == bottomCorner.getY() || - position.getX() == topCorner.getX() && position.getY() == topCorner.getY()) { - - BlocksHelper.setWithoutUpdate(world, position, portalFrame); - } else if (config.activated) { - BlocksHelper.setWithoutUpdate(world, position, portalBlock); - } - } else { - if (position.getZ() == bottomCorner.getZ() && position.getY() == bottomCorner.getY() || - position.getZ() == topCorner.getZ() && position.getY() == topCorner.getY()) { - - BlocksHelper.setWithoutUpdate(world, position, portalFrame); - } else if (config.activated) { - BlocksHelper.setWithoutUpdate(world, position, portalBlock); - } - } - } - - return true; + + public EndPortalFeature configure(Direction.Axis axis, boolean active) { + this.featureConfigured = ((DefaultEndPortalFeature) this.feature).configure(EndPortalFeatureConfig.create(frameBlock, axis, active)); + return this; } } diff --git a/src/main/resources/betterend.mixins.common.json b/src/main/resources/betterend.mixins.common.json index 14c731f7..f116f6b4 100644 --- a/src/main/resources/betterend.mixins.common.json +++ b/src/main/resources/betterend.mixins.common.json @@ -9,6 +9,7 @@ "GenerationSettingsAccessor", "DefaultBiomeCreatorMixin", "AnvilScreenHandlerMixin", + "ServerPlayerEntityMixin", "ChorusPlantFeatureMixin", "ChorusFlowerBlockMixin", "ChorusPlantBlockMixin", @@ -25,7 +26,8 @@ "LivingEntityMixin", "BoneMealItemMixin", "SlimeEntityMixin", - "BrewingAccessor" + "BrewingAccessor", + "EntityMixin" ], "injectors": { "defaultRequire": 1