-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f86dd15
commit 9523c82
Showing
10 changed files
with
414 additions
and
11 deletions.
There are no files selected for viewing
316 changes: 316 additions & 0 deletions
316
neoforge/src/main/java/io/github/realyusufismail/temporalsmith/blocks/EnderiteBlock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,316 @@ | ||
package io.github.realyusufismail.temporalsmith.blocks; | ||
|
||
import io.github.realyusufismail.temporalsmith.core.init.BlockInit; | ||
import io.github.realyusufismail.temporalsmith.core.init.DimensionsInit; | ||
import io.github.realyusufismail.temporalsmith.core.init.TagsInit; | ||
import io.github.realyusufismail.temporalsmith.dimension.ModTeleporter; | ||
import lombok.val; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.resources.ResourceKey; | ||
import net.minecraft.server.MinecraftServer; | ||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.sounds.SoundSource; | ||
import net.minecraft.util.RandomSource; | ||
import net.minecraft.world.entity.Entity; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.level.BlockGetter; | ||
import net.minecraft.world.level.Level; | ||
import net.minecraft.world.level.LevelAccessor; | ||
import net.minecraft.world.level.block.Block; | ||
import net.minecraft.world.level.block.Blocks; | ||
import net.minecraft.world.level.block.NetherPortalBlock; | ||
import net.minecraft.world.level.block.Rotation; | ||
import net.minecraft.world.level.block.state.BlockBehaviour; | ||
import net.minecraft.world.level.block.state.BlockState; | ||
import net.minecraft.world.level.block.state.StateDefinition; | ||
import net.minecraft.world.level.block.state.properties.BlockStateProperties; | ||
import net.minecraft.world.level.block.state.properties.EnumProperty; | ||
import net.minecraft.world.level.portal.PortalShape; | ||
import net.minecraft.world.phys.shapes.CollisionContext; | ||
import net.minecraft.world.phys.shapes.VoxelShape; | ||
import net.neoforged.neoforge.event.level.BlockEvent; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import static net.neoforged.neoforge.common.NeoForge.EVENT_BUS; | ||
|
||
public class EnderiteBlock extends Block { | ||
|
||
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS; | ||
protected static final VoxelShape X_AABB = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 16.0D, 10.0D); | ||
protected static final VoxelShape Z_AABB = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D); | ||
|
||
public EnderiteBlock() { | ||
super(Properties.copy(Blocks.DIAMOND_BLOCK) | ||
.strength(5.0F, 6.0F) | ||
.lightLevel((state) -> { | ||
return 15; | ||
}).noCollission()); | ||
|
||
registerDefaultState(stateDefinition.any().setValue(AXIS, Direction.Axis.X)); | ||
} | ||
|
||
|
||
@Override | ||
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { | ||
switch (state.getValue(AXIS)) { | ||
case Z: | ||
return Z_AABB; | ||
case X: | ||
default: | ||
return X_AABB; | ||
} | ||
} | ||
|
||
public boolean trySpawnPortal(LevelAccessor level, BlockPos pos) { | ||
EnderitePortalShape size = this.isPortal(level, pos); | ||
if (size != null && !onTrySpawnPortal(level, pos, size)) { | ||
size.createPortalBlocks(); | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
public static boolean onTrySpawnPortal(LevelAccessor world, BlockPos pos, EnderitePortalShape size) { | ||
val spawn = EVENT_BUS.post(new BlockEvent.PortalSpawnEvent(world, pos, world.getBlockState(pos), size)); | ||
return spawn.isCanceled(); | ||
} | ||
|
||
@Nullable | ||
public EnderitePortalShape isPortal(LevelAccessor level, BlockPos pos) { | ||
EnderitePortalShape EnderitePortalBlockSize = new EnderitePortalShape(level, pos, Direction.Axis.X); | ||
if (EnderitePortalBlockSize.isValid() && EnderitePortalBlockSize.numPortalBlocks == 0) { | ||
return EnderitePortalBlockSize; | ||
} else { | ||
EnderitePortalShape EnderitePortalBlockSize1 = new EnderitePortalShape(level, pos, Direction.Axis.Z); | ||
return EnderitePortalBlockSize1.isValid() && EnderitePortalBlockSize1.numPortalBlocks == 0 ? EnderitePortalBlockSize1 : null; | ||
} | ||
} | ||
|
||
@Override | ||
public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { | ||
Direction.Axis directionAxis = facing.getAxis(); | ||
Direction.Axis directionAxis1 = stateIn.getValue(AXIS); | ||
boolean flag = directionAxis1 != directionAxis && directionAxis.isHorizontal(); | ||
return !flag && facingState.getBlock() != this && !(new EnderitePortalShape(level, currentPos, directionAxis1)).isComplete() ? Blocks.AIR.defaultBlockState() : super.updateShape(stateIn, facing, facingState, level, currentPos, facingPos); | ||
} | ||
|
||
@Override | ||
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { | ||
if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { | ||
if (entity.isOnPortalCooldown()) { | ||
entity.setPortalCooldown(); | ||
} else { | ||
if (!entity.level().isClientSide() && !pos.equals(entity.portalEntrancePos)) { | ||
entity.portalEntrancePos = pos.immutable(); | ||
} | ||
Level level1 = entity.level(); | ||
if (level1 != null) { | ||
MinecraftServer minecraftserver = level1.getServer(); | ||
ResourceKey<Level> destination = entity.level().dimension() == DimensionsInit.CHRONO_REALM ? Level.OVERWORLD : DimensionsInit.CHRONO_REALM; | ||
if (minecraftserver != null) { | ||
ServerLevel destinationWorld = minecraftserver.getLevel(destination); | ||
if (destinationWorld != null && minecraftserver.isNetherEnabled() && !entity.isPassenger()) { | ||
entity.level().getProfiler().push("undergarden_portal"); | ||
entity.setPortalCooldown(); | ||
entity.changeDimension(destinationWorld, new ModTeleporter(destinationWorld)); | ||
entity.level().getProfiler().pop(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { | ||
if (random.nextInt(100) == 0) { | ||
level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, UGSoundEvents.UNDERGARDEN_PORTAL_AMBIENT.get(), SoundSource.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F, false); | ||
} | ||
|
||
for (int i = 0; i < 4; ++i) { | ||
double x = (double) pos.getX() + random.nextDouble(); | ||
double y = (double) pos.getY() + random.nextDouble(); | ||
double z = (double) pos.getZ() + random.nextDouble(); | ||
double xSpeed = ((double) random.nextFloat() - 0.5D) * 0.5D; | ||
double ySpeed = ((double) random.nextFloat() - 0.5D) * 0.5D; | ||
double zSpeed = ((double) random.nextFloat() - 0.5D) * 0.5D; | ||
int j = random.nextInt(2) * 2 - 1; | ||
if (!level.getBlockState(pos.west()).is(this) && !level.getBlockState(pos.east()).is(this)) { | ||
x = (double) pos.getX() + 0.5D + 0.25D * (double) j; | ||
xSpeed = random.nextFloat() * 2.0F * (float) j; | ||
} else { | ||
z = (double) pos.getZ() + 0.5D + 0.25D * (double) j; | ||
zSpeed = random.nextFloat() * 2.0F * (float) j; | ||
} | ||
|
||
level.addParticle(UGParticleTypes.UNDERGARDEN_PORTAL.get(), x, y, z, xSpeed, ySpeed, zSpeed); | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState state) { | ||
return ItemStack.EMPTY; | ||
} | ||
|
||
@Override | ||
public BlockState rotate(BlockState state, Rotation rot) { | ||
switch (rot) { | ||
case COUNTERCLOCKWISE_90: | ||
case CLOCKWISE_90: | ||
switch (state.getValue(AXIS)) { | ||
case Z: | ||
return state.setValue(AXIS, Direction.Axis.X); | ||
case X: | ||
return state.setValue(AXIS, Direction.Axis.Z); | ||
default: | ||
return state; | ||
} | ||
default: | ||
return state; | ||
} | ||
} | ||
|
||
@Override | ||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { | ||
builder.add(AXIS); | ||
} | ||
|
||
//copy of Minecraft's PortalShape, frame and portal blocks changed accordingly | ||
public static class EnderitePortalShape extends PortalShape { | ||
private static final int MIN_WIDTH = 1; | ||
public static final int MAX_WIDTH = 21; | ||
private static final int MIN_HEIGHT = 2; | ||
public static final int MAX_HEIGHT = 21; | ||
private static final BlockBehaviour.StatePredicate FRAME = (state, getter, pos) -> state.is(TagsInit.BlockTagsInit.PORTAL_FRAME_BLOCKS); | ||
private final LevelAccessor level; | ||
private final Direction.Axis axis; | ||
private final Direction rightDir; | ||
private int numPortalBlocks; | ||
private BlockPos bottomLeft; | ||
private int height; | ||
private final int width; | ||
|
||
public EnderitePortalShape(LevelAccessor level, BlockPos bottomLeftPos, Direction.Axis axis) { | ||
super(level, bottomLeftPos, axis); | ||
this.level = level; | ||
this.axis = axis; | ||
this.rightDir = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; | ||
this.bottomLeft = this.calculateBottomLeft(bottomLeftPos); | ||
if (this.bottomLeft == null) { | ||
this.bottomLeft = bottomLeftPos; | ||
this.width = 1; | ||
this.height = 1; | ||
} else { | ||
this.width = this.calculateWidth(); | ||
if (this.width > 0) { | ||
this.height = this.calculateHeight(); | ||
} | ||
} | ||
|
||
} | ||
|
||
@Nullable | ||
private BlockPos calculateBottomLeft(BlockPos pos) { | ||
for (int i = Math.max(this.level.getMinBuildHeight(), pos.getY() - MAX_HEIGHT); pos.getY() > i && isEmpty(this.level.getBlockState(pos.below())); pos = pos.below()) { | ||
} | ||
|
||
Direction direction = this.rightDir.getOpposite(); | ||
int j = this.getDistanceUntilEdgeAboveFrame(pos, direction) - 1; | ||
return j < 0 ? null : pos.relative(direction, j); | ||
} | ||
|
||
private int calculateWidth() { | ||
int i = this.getDistanceUntilEdgeAboveFrame(this.bottomLeft, this.rightDir); | ||
return i >= MIN_WIDTH && i <= MAX_WIDTH ? i : 0; | ||
} | ||
|
||
private int getDistanceUntilEdgeAboveFrame(BlockPos pos, Direction direction) { | ||
BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); | ||
|
||
for (int i = 0; i <= MAX_WIDTH; ++i) { | ||
mutablePos.set(pos).move(direction, i); | ||
BlockState blockstate = this.level.getBlockState(mutablePos); | ||
if (!isEmpty(blockstate)) { | ||
if (FRAME.test(blockstate, this.level, mutablePos)) { | ||
return i; | ||
} | ||
break; | ||
} | ||
|
||
BlockState blockstate1 = this.level.getBlockState(mutablePos.move(Direction.DOWN)); | ||
if (!FRAME.test(blockstate1, this.level, mutablePos)) { | ||
break; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
private int calculateHeight() { | ||
BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); | ||
int i = this.getDistanceUntilTop(mutablePos); | ||
return i >= MIN_HEIGHT && i <= MAX_HEIGHT && this.hasTopFrame(mutablePos, i) ? i : 0; | ||
} | ||
|
||
private boolean hasTopFrame(BlockPos.MutableBlockPos pos, int height) { | ||
for (int i = 0; i < this.width; ++i) { | ||
BlockPos.MutableBlockPos mutablePos = pos.set(this.bottomLeft).move(Direction.UP, height).move(this.rightDir, i); | ||
if (!FRAME.test(this.level.getBlockState(mutablePos), this.level, mutablePos)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private int getDistanceUntilTop(BlockPos.MutableBlockPos pos) { | ||
for (int i = 0; i < MAX_HEIGHT; ++i) { | ||
pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1); | ||
if (!FRAME.test(this.level.getBlockState(pos), this.level, pos)) { | ||
return i; | ||
} | ||
|
||
pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width); | ||
if (!FRAME.test(this.level.getBlockState(pos), this.level, pos)) { | ||
return i; | ||
} | ||
|
||
for (int j = 0; j < this.width; ++j) { | ||
pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, j); | ||
BlockState blockstate = this.level.getBlockState(pos); | ||
if (!isEmpty(blockstate)) { | ||
return i; | ||
} | ||
|
||
if (blockstate.is(Blocks.NETHER_PORTAL)) { | ||
++this.numPortalBlocks; | ||
} | ||
} | ||
} | ||
|
||
return MAX_HEIGHT; | ||
} | ||
|
||
private static boolean isEmpty(BlockState state) { | ||
return state.isAir() || state.is(BlockInit.ENDERITE_BLOCK.get()); | ||
} | ||
|
||
public boolean isValid() { | ||
return this.bottomLeft != null && this.width >= MIN_WIDTH && this.width <= MAX_WIDTH && this.height >= MIN_HEIGHT && this.height <= MAX_HEIGHT; | ||
} | ||
|
||
public void createPortalBlocks() { | ||
BlockState blockstate = BlockInit.ENDERITE_BLOCK.get().defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); | ||
BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach(pos -> this.level.setBlock(pos, blockstate, 18)); | ||
} | ||
|
||
public boolean isComplete() { | ||
return this.isValid() && this.numPortalBlocks == this.width * this.height; | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
neoforge/src/main/java/io/github/realyusufismail/temporalsmith/dimension/ModTeleporter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package io.github.realyusufismail.temporalsmith.dimension; | ||
|
||
import io.github.realyusufismail.temporalsmith.core.init.POIInit; | ||
import net.minecraft.BlockUtil; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.resources.ResourceLocation; | ||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.server.level.TicketType; | ||
import net.minecraft.world.entity.ai.village.poi.PoiManager; | ||
import net.minecraft.world.entity.ai.village.poi.PoiRecord; | ||
import net.minecraft.world.level.ChunkPos; | ||
import net.minecraft.world.level.block.Blocks; | ||
import net.minecraft.world.level.block.state.BlockState; | ||
import net.minecraft.world.level.block.state.properties.BlockStateProperties; | ||
import net.neoforged.neoforge.common.util.ITeleporter; | ||
import net.neoforged.neoforge.registries.ForgeRegistries; | ||
|
||
import java.util.Comparator; | ||
import java.util.Optional; | ||
|
||
public class ModTeleporter implements ITeleporter { | ||
|
||
protected final ServerLevel level; | ||
|
||
public ModTeleporter(ServerLevel level) { | ||
this.level = level; | ||
} | ||
|
||
public Optional<BlockUtil.FoundRectangle> getExistingPortal(BlockPos pos) { | ||
PoiManager poiManager = this.level.getPoiManager(); | ||
poiManager.ensureLoadedAndValid(this.level, pos, 64); | ||
Optional<PoiRecord> optional = poiManager.getInSquare((poiType) -> | ||
poiType.is(POIInit.ENDERITE_BLOCK), pos, 64, PoiManager.Occupancy.ANY).sorted(Comparator.<PoiRecord>comparingDouble((poi) -> | ||
poi.getPos().distSqr(pos)).thenComparingInt((poi) -> | ||
poi.getPos().getY())).filter((poi) -> | ||
this.level.getBlockState(poi.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS)).findFirst(); | ||
return optional.map((poi) -> { | ||
BlockPos blockpos = poi.getPos(); | ||
this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockpos), 3, blockpos); | ||
BlockState blockstate = this.level.getBlockState(blockpos); | ||
return BlockUtil.getLargestRectangleAround(blockpos, blockstate.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockPos) -> | ||
this.level.getBlockState(blockPos) == blockstate); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.