From 5a3f8c94e6e0b2ddd3cd2ba678075149a8f1f337 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Sat, 1 Aug 2020 19:28:24 -0400 Subject: [PATCH] Implement Energy Portal --- build.gradle | 3 +- .../block/portal/EnergyPortalBlock.java | 29 +++++-- .../block/portal/EnergyTeleporter.java | 81 +++++++++++++++++++ .../energonrelics/config/HardcodedConfig.java | 3 +- .../resources/energonrelics.accesswidener | 2 + src/main/resources/fabric.mod.json | 1 + 6 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyTeleporter.java create mode 100644 src/main/resources/energonrelics.accesswidener diff --git a/build.gradle b/build.gradle index 84a5c4b..4763c9c 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,8 @@ compileJava { version = project.mod_version group = project.maven_group -minecraft { +loom { + accessWidener "src/main/resources/energonrelics.accesswidener" } repositories { diff --git a/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyPortalBlock.java b/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyPortalBlock.java index 68e3472..7c0849f 100644 --- a/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyPortalBlock.java +++ b/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyPortalBlock.java @@ -2,12 +2,18 @@ package com.thebrokenrail.energonrelics.block.portal; import com.thebrokenrail.energonrelics.EnergonRelics; import com.thebrokenrail.energonrelics.block.util.SimpleBlock; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.ShapeContext; import net.minecraft.block.piston.PistonBehavior; import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.function.BooleanBiFunction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; @@ -16,6 +22,8 @@ import net.minecraft.world.BlockView; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; +import java.util.Random; + @SuppressWarnings("deprecation") public class EnergyPortalBlock extends SimpleBlock { public EnergyPortalBlock() { @@ -27,11 +35,6 @@ public class EnergyPortalBlock extends SimpleBlock { return false; } - @Override - public VoxelShape getVisualShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { - return VoxelShapes.empty(); - } - private static final VoxelShape SHAPE = createCuboidShape(0, 6, 0, 16, 10, 16); @Override @@ -65,7 +68,7 @@ public class EnergyPortalBlock extends SimpleBlock { return validSides == 4; } - private static BlockPos getCenterPos(WorldAccess world, BlockPos pos) { + static BlockPos getCenterPos(WorldAccess world, BlockPos pos) { BlockPos centerPos = pos; for (Direction side : Direction.values()) { if (isValidDirection(side)) { @@ -137,9 +140,19 @@ public class EnergyPortalBlock extends SimpleBlock { public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { super.onEntityCollision(state, world, pos, entity); - if (!world.isClient() && !entity.hasVehicle() && entity.canUsePortals() && ((PortalCooldownEntity) entity).isEnergyPortalCooldown()) { - // Teleport + if (!world.isClient() && !entity.hasVehicle() && entity.canUsePortals() && !((PortalCooldownEntity) entity).isEnergyPortalCooldown() && VoxelShapes.matchesAnywhere(VoxelShapes.cuboid(entity.getBoundingBox().offset(-pos.getX(), -pos.getY(), -pos.getZ())), state.getOutlineShape(world, pos), BooleanBiFunction.AND)) { ((PortalCooldownEntity) entity).resetEnergyPortalCooldown(); + EnergyTeleporter.teleport((ServerWorld) world, entity.getPos(), pos, entity); + } + } + + @Environment(EnvType.CLIENT) + @Override + public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) { + super.randomDisplayTick(state, world, pos, random); + + if (random.nextInt(100) == 0) { + world.playSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.BLOCK_PORTAL_AMBIENT, SoundCategory.BLOCKS, 0.5f, random.nextFloat() * 0.4f + 0.8f, false); } } } diff --git a/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyTeleporter.java b/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyTeleporter.java new file mode 100644 index 0000000..e05709d --- /dev/null +++ b/src/main/java/com/thebrokenrail/energonrelics/block/portal/EnergyTeleporter.java @@ -0,0 +1,81 @@ +package com.thebrokenrail.energonrelics.block.portal; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.thebrokenrail.energonrelics.config.HardcodedConfig; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; +import net.minecraft.server.command.TeleportCommand; +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.Heightmap; +import net.minecraft.world.World; + +import java.util.EnumSet; + +class EnergyTeleporter { + private static void teleport(Entity entity, ServerWorld to, Vec3d pos) { + try { + TeleportCommand.teleport(null, entity, to, pos.getX(), pos.getY(), pos.getZ(), EnumSet.noneOf(PlayerPositionLookS2CPacket.Flag.class), entity.yaw, entity.pitch, null); + } catch (CommandSyntaxException ignored) { + } + } + + static void teleport(ServerWorld world, Vec3d pos, BlockPos blockPos, Entity entity) { + BlockPos center = EnergyPortalBlock.getCenterPos(world, blockPos); + Vec3d offset = pos.subtract(Vec3d.ofBottomCenter(center)); + + RegistryKey worldKey = world.getRegistryKey(); + if (worldKey == World.OVERWORLD) { + teleportWithMultiplier(world, entity, center, offset, World.NETHER, 1d / HardcodedConfig.ENERGY_PORTAL_MULTIPLIER); + } else if (worldKey == World.NETHER) { + teleportWithMultiplier(world, entity, center, offset, World.OVERWORLD, HardcodedConfig.ENERGY_PORTAL_MULTIPLIER); + } else { + teleportToWorldSpawn(world, entity); + } + } + + private static void teleportWithMultiplier(ServerWorld world, Entity entity, BlockPos center, Vec3d offset, RegistryKey toKey, double multiplier) { + ServerWorld to = world.getServer().getWorld(toKey); + assert to != null; + + float yMultiplier = (float) to.getDimensionHeight() / (float) world.getDimensionHeight(); + int y = (int) (center.getY() * yMultiplier); + + int x = (int) (center.getX() * multiplier); + int z = (int) (center.getZ() * multiplier); + + BlockPos targetBlock = new BlockPos(x, y, z); + + BlockPos start = targetBlock.add(-1, -1, -1); + for (int xPos = 0; xPos < 3; xPos++) { + for (int yPos = 0; yPos < 4; yPos++) { + for (int zPos = 0; zPos < 3; zPos++) { + BlockPos pos = start.add(xPos, yPos, zPos); + BlockState oldState = to.getBlockState(pos); + if (oldState.getHardness(world, pos) >= 0) { + Block block = yPos == 0 ? Blocks.OBSIDIAN : Blocks.AIR; + BlockState state = block.getDefaultState(); + to.setBlockState(pos, state); + } + } + } + } + + Vec3d target = Vec3d.ofBottomCenter(targetBlock).add(offset); + target = new Vec3d(target.getX(), Math.max(0, target.getY()), target.getZ()); + + teleport(entity, to, target); + } + + private static void teleportToWorldSpawn(ServerWorld world, Entity entity) { + ServerWorld to = world.getServer().getWorld(World.OVERWORLD); + assert to != null; + BlockPos dest = to.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, to.getSpawnPos()); + teleport(entity, to, Vec3d.ofBottomCenter(dest)); + } +} diff --git a/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java b/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java index c65428e..a34aa20 100644 --- a/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java +++ b/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java @@ -46,5 +46,6 @@ public class HardcodedConfig { public static final int INFUSER_TIME = 2200; public static final long ENERGY_PROJECTOR_ENERGY_REQUIRED = 37; - public static final int ENERGY_PORTAL_COOLDOWN = 20; + public static final int ENERGY_PORTAL_COOLDOWN = 28; + public static final int ENERGY_PORTAL_MULTIPLIER = 32; } \ No newline at end of file diff --git a/src/main/resources/energonrelics.accesswidener b/src/main/resources/energonrelics.accesswidener new file mode 100644 index 0000000..38f9695 --- /dev/null +++ b/src/main/resources/energonrelics.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 named +accessible method net/minecraft/server/command/TeleportCommand teleport (Lnet/minecraft/server/command/ServerCommandSource;Lnet/minecraft/entity/Entity;Lnet/minecraft/server/world/ServerWorld;DDDLjava/util/Set;FFLnet/minecraft/server/command/TeleportCommand$LookTarget;)V \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index d36b7ee..f759428 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -32,6 +32,7 @@ "mixins": [ "energonrelics.mixins.json" ], + "accessWidener" : "energonrelics.accesswidener", "depends": { "fabricloader": ">=0.7.4", "fabric": "*",