diff --git a/build.gradle.kts b/build.gradle.kts index a52e721d8..2b5d1285c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,6 @@ val loaderVersion: String by properties val javaVersion: String by properties val fabricApiVersion: String by properties -val incubusCoreVersion: String by properties val customportalapiVersion: String by properties val cardinalComponentsVersion: String by properties val trinketsVersion: String by properties @@ -128,12 +127,6 @@ dependencies { version = fabricApiVersion, ) - modImplementation( - group = "com.github.devs-immortal", - name = "Incubus-Core", - version = incubusCoreVersion, - ).also(::include) - modImplementation( group = "com.jamieswhiteshirt", name = "reach-entity-attributes", diff --git a/gradle.properties b/gradle.properties index c313da163..b84987aba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,18 @@ # suppress inspection "UnusedProperty" for whole file org.gradle.jvmargs=-Xmx2G -paradiseLostVersion=2.2.1-beta+1.19.2 +paradiseLostVersion=2.2.1-beta+1.19.4 -minecraftVersion=1.19.2 -yarnVersion=1.19.2+build.28 -loaderVersion=0.15.7 +minecraftVersion=1.19.4 +yarnVersion=1.19.4+build.2 +loaderVersion=0.15.11 javaVersion=17 -fabricApiVersion=0.77.0+1.19.2 -incubusCoreVersion=2.0.0 +fabricApiVersion=0.87.2+1.19.4 customportalapiVersion=0.0.1-beta63.5-1.19.X cardinalComponentsVersion=5.0.1 trinketsVersion=3.4.0 -crowdinTranslateVersion=1.19.2 +crowdinTranslateVersion=1.19.4 entityAttributesVersion=2.3.0 modmenuVersion=4.0.6 reiVersion=9.1.530 diff --git a/src/main/java/net/id/paradiselost/api/BlockLikeEntity.java b/src/main/java/net/id/paradiselost/api/BlockLikeEntity.java new file mode 100644 index 000000000..b361de675 --- /dev/null +++ b/src/main/java/net/id/paradiselost/api/BlockLikeEntity.java @@ -0,0 +1,446 @@ +package net.id.paradiselost.api; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.id.paradiselost.entities.util.PostTickEntity; +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.*; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.data.*; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.AutomaticItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.*; +import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; +import net.minecraft.registry.tag.BlockTags; +import net.minecraft.registry.tag.FluidTags; +import net.minecraft.state.property.Properties; +import net.minecraft.util.crash.CrashReportSection; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.*; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.*; +import java.util.List; + +/** + * An entity that resembles a block. + */ +public abstract class BlockLikeEntity extends Entity implements PostTickEntity { + private static final TrackedData ORIGIN = DataTracker.registerData(BlockLikeEntity.class, TrackedDataHandlerRegistry.BLOCK_POS); + public int moveTime; + public boolean dropItem = true; + protected NbtCompound blockEntityData; + protected BlockState blockState = Blocks.STONE.getDefaultState(); + protected boolean canSetBlock = true; + protected boolean hurtEntities = false; + protected int fallHurtMax = 40; + protected float fallHurtAmount = 2.0f; + protected boolean collides; + protected boolean partOfSet = false; + + public BlockLikeEntity(EntityType entityType, World world) { + super(entityType, world); + this.moveTime = 0; + } + + public BlockLikeEntity(EntityType entityType, World world, double x, double y, double z, BlockState blockState) { + this(entityType, world); + this.blockState = blockState; + this.intersectionChecked = true; + this.setPosition(x, y, z); + this.setVelocity(Vec3d.ZERO); + this.prevX = x; + this.prevY = y; + this.prevZ = z; + this.setOrigin(this.getBlockPos()); + } + + public BlockLikeEntity(EntityType entityType, World world, BlockPos pos, BlockState blockState, boolean partOfSet) { + this(entityType, world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, blockState); + this.partOfSet = partOfSet; + } + + /** + * Calculates the bounding box based on the blockstate's collision shape. + * If the blockstate doesn't have collision, this method turns collision + * off for this entity and sets the bounding box to the outline shape instead. + * Note: Complex bounding boxes are not supported. These are all rectangular prisms. + * @return The bounding box of this entity + */ + @Override + protected Box calculateBoundingBox() { + if (this.dataTracker == null || this.blockState == null) { + return super.calculateBoundingBox(); + } + BlockPos origin = this.dataTracker.get(ORIGIN); + VoxelShape shape = this.blockState.getCollisionShape(world, origin); + if (shape.isEmpty()) { + this.collides = false; + shape = this.blockState.getOutlineShape(world, origin); + if (shape.isEmpty()) { + return super.calculateBoundingBox(); + } + } else { + this.collides = true; + } + Box box = shape.getBoundingBox(); + return box.offset(getPos().subtract(new Vec3d(0.5, 0, 0.5))); + } + + @Override + public void tick() { + // recalculate fall damage + if (this.hurtEntities) { + double verticalSpeed = Math.abs(this.getVelocity().getY()); + this.fallHurtAmount = this.blockState.getBlock().getHardness() * (float)verticalSpeed; + this.fallHurtMax = Math.max(Math.round(this.fallHurtAmount), this.fallHurtMax); + } + } + + /** + * Override me! Calculate movement. + */ + public abstract void postTickMovement(); + + /** + * Take actions on entities on "collision". + * By default, it replicates the blockstate's behavior on collision. + */ + public void postTickEntityCollision(Entity entity) { + if (!(entity instanceof BlockLikeEntity ble && ble.partOfSet)) { + this.blockState.onEntityCollision(world, this.getBlockPos(), entity); + } + } + + /** + * @return Whether this entity should cease and return to being a block in the world. + */ + public boolean shouldCease() { + if (this.world.isClient) return false; + + BlockPos blockPos = this.getBlockPos(); + boolean isConcrete = this.blockState.getBlock() instanceof ConcretePowderBlock; + + if (isConcrete && this.world.getFluidState(blockPos).isIn(FluidTags.WATER)) { + return true; + } + + double speed = this.getVelocity().lengthSquared(); + + if (isConcrete && speed > 1.0D) { + BlockHitResult blockHitResult = this.world.raycast(new RaycastContext( + new Vec3d(this.prevX, this.prevY, this.prevZ), + new Vec3d(this.getX(), this.getY(), this.getZ()), + RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.SOURCE_ONLY, this) + ); + + if (blockHitResult.getType() != HitResult.Type.MISS + && this.world.getFluidState(blockHitResult.getBlockPos()).isIn(FluidTags.WATER)) { + return true; + } + } + + // Check if it is outside of the world + return this.moveTime > 100 && (blockPos.getY() < this.world.getBottomY() || blockPos.getY() > this.world.getTopY()); + } + + /** + * The big kahuna. You likely don't need to override this method. + * Instead, override the methods that it calls. + */ + public void incubus_Concern$postTick() { + if (this.blockState.isAir()) { + this.discard(); + return; + } + + this.prevX = this.getX(); + this.prevY = this.getY(); + this.prevZ = this.getZ(); + + // Destroy the block in the world that this is spawned from + // If no block exists, remove this entity (unless part of a set) + if (this.moveTime++ == 0) { + BlockPos blockPos = this.getBlockPos(); + Block block = this.blockState.getBlock(); + if (this.world.getBlockState(blockPos).isOf(block)) { + this.world.removeBlock(blockPos, false); + } else if (!this.world.isClient && !this.partOfSet) { + this.discard(); + return; + } + } + + this.postTickMovement(); + + this.postTickMoveEntities(); + + if (this.shouldCease()) this.cease(); + } + + /** + * You likely won't need to override this method, but it imparts this block's + * momentum onto other entities. + */ + public void postTickMoveEntities() { + if (FallingBlock.canFallThrough(this.blockState)) return; + + List otherEntities = this.world.getOtherEntities(this, getBoundingBox().union(getBoundingBox().offset(0, 0.5, 0))); + for (var entity : otherEntities) { + if (!(entity instanceof BlockLikeEntity) && !entity.noClip && collides) { + entity.move(MovementType.SHULKER_BOX, this.getVelocity()); + entity.setOnGround(true); + + // If we're about to stop touching, give the entity momentum. + if (!entity.getBoundingBox().offset(entity.getVelocity().multiply(2)).intersects( + this.getBoundingBox().offset(this.getVelocity().multiply(2)))) { + entity.setVelocity(entity.getVelocity().add(this.getVelocity())); + } + } + this.postTickEntityCollision(entity); + } + } + + @Override + public boolean handleFallDamage(float distance, float multiplier, DamageSource damageSource) { + int i = MathHelper.ceil(distance - 1.0F); + + if (!this.hurtEntities || i <= 0) { + return false; + } + + boolean flag = this.blockState.isIn(BlockTags.ANVIL); + DamageSource damageSource2 = flag ? DamageSource.ANVIL : DamageSource.FALLING_BLOCK; + float f = Math.min(MathHelper.floor((float)i * this.fallHurtAmount), this.fallHurtMax); + + this.world.getOtherEntities(this, getBoundingBox().union(getBoundingBox().offset(0, 1 + -2 * this.getVelocity().getY(), 0))).forEach(entity -> entity.damage(damageSource2, f)); + + if (flag && f > 0.0F && this.random.nextFloat() < 0.05F + i * 0.05F) { + BlockState blockstate = AnvilBlock.getLandingState(this.blockState); + if (blockstate == null) { + this.canSetBlock = false; + } else this.blockState = blockstate; + } + return false; + } + + @Override + protected void writeCustomDataToNbt(NbtCompound compound) { + compound.put("BlockState", NbtHelper.fromBlockState(this.blockState)); + compound.putInt("Time", this.moveTime); + compound.putBoolean("DropItem", this.dropItem); + compound.putBoolean("HurtEntities", this.hurtEntities); + compound.putFloat("FallHurtAmount", this.fallHurtAmount); + compound.putInt("FallHurtMax", this.fallHurtMax); + if (this.blockEntityData != null) { + compound.put("TileEntityData", this.blockEntityData); + } + } + + @Override + protected void readCustomDataFromNbt(NbtCompound compound) { + this.blockState = NbtHelper.toBlockState(compound.getCompound("BlockState")); + this.moveTime = compound.getInt("Time"); + if (compound.contains("HurtEntities", 99)) { + this.hurtEntities = compound.getBoolean("HurtEntities"); + this.fallHurtAmount = compound.getFloat("FallHurtAmount"); + this.fallHurtMax = compound.getInt("FallHurtMax"); + } else if (this.blockState.isIn(BlockTags.ANVIL)) { + this.hurtEntities = true; + } + + if (compound.contains("DropItem", 99)) this.dropItem = compound.getBoolean("DropItem"); + + if (compound.contains("TileEntityData", 10)) this.blockEntityData = compound.getCompound("TileEntityData"); + + if (this.blockState.isAir()) this.blockState = Blocks.STONE.getDefaultState(); + } + + @Environment(EnvType.CLIENT) + public World getWorldObj() { + return this.world; + } + + @Override + public boolean doesRenderOnFire() { + return false; + } + + @Override + public void populateCrashReport(CrashReportSection section) { + super.populateCrashReport(section); + section.add("Imitating BlockState", this.blockState.toString()); + } + + public BlockState getBlockState() { + return this.blockState; + } + + public void setHurtEntities(boolean hurtEntities) { + this.hurtEntities = hurtEntities; + } + + /** + * End entity movement and become a block in the world (Removes this entity). + */ + public void cease() { + if (this.isRemoved()) { + return; + } + BlockPos pos = this.getBlockPos(); + BlockState state = this.world.getBlockState(pos); + // I don't like this + if (state.isOf(Blocks.MOVING_PISTON)) { + this.setVelocity(this.getVelocity().multiply(0.7, 0.5, 0.7)); + return; + } + if (!this.trySetBlock()) { + this.breakApart(); + } + } + + /** + * Tries to set the block + * @return {@code true} if the block can be set + */ + public boolean trySetBlock() { + BlockPos blockPos = this.getBlockPos(); + BlockState blockState = this.world.getBlockState(blockPos); + boolean canReplace = blockState.canReplace(new AutomaticItemPlacementContext(this.world, blockPos, Direction.UP, ItemStack.EMPTY, Direction.DOWN)); + boolean canPlace = this.blockState.canPlaceAt(this.world, blockPos); + + if (!this.canSetBlock || !canPlace || !canReplace) + return false; + + if (this.blockState.contains(Properties.WATERLOGGED) && this.world.getFluidState(blockPos).getFluid() == Fluids.WATER) { + this.blockState = this.blockState.with(Properties.WATERLOGGED, true); + } + + if (this.world.setBlockState(blockPos, this.blockState, Block.NOTIFY_ALL)) { + this.discard(); + if (this.blockEntityData != null && this.blockState.hasBlockEntity()) { + BlockEntity blockEntity = this.world.getBlockEntity(blockPos); + if (blockEntity != null) { + NbtCompound compoundTag = blockEntity.createNbt(); + for (String keyName : this.blockEntityData.getKeys()) { + NbtElement tag = this.blockEntityData.get(keyName); + if (tag != null && !"x".equals(keyName) && !"y".equals(keyName) && !"z".equals(keyName)) { + compoundTag.put(keyName, tag.copy()); + } + } + + blockEntity.readNbt(compoundTag); + blockEntity.markDirty(); + } + } + for (Direction dir : Direction.stream().toList()) { + var newState = this.blockState.getStateForNeighborUpdate( + dir, + this.world.getBlockState(blockPos.offset(dir)), + this.world, + blockPos, + blockPos.offset(dir) + ); + this.world.setBlockState(blockPos, newState); + this.blockState = newState; + } + world.scheduleBlockTick(blockPos, this.blockState.getBlock(), 1); + // Stop entities from clipping through the block when it's set + this.postTickMoveEntities(); + return true; + } + return false; + } + + /** + * Break the block, spawn break particles, and drop stacks if it can. + */ + public void breakApart() { + if (this.isRemoved()) return; + + this.discard(); + if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { + Block.dropStacks(this.blockState, this.world, this.getBlockPos()); + } + // spawn break particles + world.syncWorldEvent(null, WorldEvents.BLOCK_BROKEN, this.getBlockPos(), Block.getRawIdFromState(blockState)); + } + + @Override + public boolean entityDataRequiresOperator() { + return true; + } + + @Override + public EntitySpawnS2CPacket createSpawnPacket() { + return new EntitySpawnS2CPacket(this, Block.getRawIdFromState(this.getBlockState()) * (this.partOfSet ? -1 : 1)); + } + + @Override + public void onSpawnPacket(EntitySpawnS2CPacket packet) { + super.onSpawnPacket(packet); + int data = packet.getEntityData(); + this.partOfSet = data < 0; + this.blockState = Block.getStateFromRawId(packet.getEntityData() * (this.partOfSet ? -1 : 1)); + this.intersectionChecked = true; + double d = packet.getX(); + double e = packet.getY(); + double f = packet.getZ(); + this.setPosition(d, e + (double) ((1.0F - this.getHeight()) / 2.0F), f); + this.setOrigin(this.getBlockPos()); + } + + /** + * Aligns this block to another. + * @param other The other block to align with + * @param offset The offset from the other block. this pos - other pos. + * @see BlockLikeSet + */ + public void alignWith(BlockLikeEntity other, Vec3i offset) { + if (this == other) return; + Vec3d newPos = other.getPos().add(Vec3d.of(offset)); + this.setPos(newPos.x, newPos.y, newPos.z); + this.setVelocity(other.getVelocity()); + } + + @Override + public boolean isAttackable() { + return false; + } + + @Environment(EnvType.CLIENT) + public BlockPos getOrigin() { + return this.dataTracker.get(ORIGIN); + } + + public void setOrigin(BlockPos origin) { + this.dataTracker.set(ORIGIN, origin); + this.setPosition(getX(), getY(), getZ()); + } + + public void markPartOfSet() { + this.partOfSet = true; + } + + @Override + protected void initDataTracker() { + this.dataTracker.startTracking(ORIGIN, BlockPos.ORIGIN); + } + + //@Override + //public boolean collides() { + // return !this.isRemoved() && this.collides; + //} + + @Override + public boolean isCollidable() { + return collides; + } + + @Override + public boolean collidesWith(Entity other) { + return !(other instanceof BlockLikeEntity) && super.collidesWith(other); + } +} diff --git a/src/main/java/net/id/paradiselost/api/BlockLikeSet.java b/src/main/java/net/id/paradiselost/api/BlockLikeSet.java new file mode 100644 index 000000000..af698876d --- /dev/null +++ b/src/main/java/net/id/paradiselost/api/BlockLikeSet.java @@ -0,0 +1,189 @@ +package net.id.paradiselost.api; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import java.util.*; +import java.util.function.Predicate; + +/** + * An object designed to hold {@link BlockLikeEntity}s together. + *
These are ticked every post-tick until destroyed. (Similar to {@link net.id.paradiselost.entities.util.PostTickEntity}) + * @author Jack Papel + */ +@SuppressWarnings("unused") +public class BlockLikeSet { + private static final Set structures = new HashSet<>(); + private final Map entries; + + /** + * This constructor is useful for doors and other two-block {@link BlockLikeSet}s. + * @param offset entity2's position - entity1's position + */ + public BlockLikeSet(BlockLikeEntity entity1, BlockLikeEntity entity2, Vec3i offset) { + this.entries = Map.of( + Vec3i.ZERO, entity1, + offset, entity2 + ); + } + + /** + * One of the entries in this map must have an offset of {@link Vec3i#ZERO}. + *
"Must" is a strong word. It's recommended. If it isn't the case, the physics won't be consistent, probably. + */ + public BlockLikeSet(Map map) { + this.entries = map; + } + + /** + * @return An unordered iterator of all active {@link BlockLikeSet}s. Active means the set has not landed. + */ + public static Iterator getAllSets() { + return Set.copyOf(structures).iterator(); + } + + /** + * @return An immutable copy of this {@link BlockLikeSet}'s entries. + */ + public Map getEntries(){ + return Map.copyOf(entries); + } + + public void spawn(World world) { + entries.forEach((offset, block) -> { + block.markPartOfSet(); + world.removeBlock(block.getBlockPos(), false); + world.spawnEntity(block); + }); + init(); + } + + // Aligns all BLEs to the master block + protected void synchronize() { + BlockLikeEntity master = getMasterBlock(); + entries.forEach((offset, block) -> block.alignWith(master, offset)); + } + + public void postTick() { + this.synchronize(); + + for (BlockLikeEntity block : entries.values()) { + if (block.isRemoved()) { + // If one block ceases, the rest must as well. + World world = block.world; + BlockState state = block.getBlockState(); + boolean success = world.getBlockState(block.getBlockPos()).isOf(state.getBlock()); + this.land(block, success); + break; + } + } + } + + public void land(BlockLikeEntity lander, boolean success) { + this.synchronize(); + + for (BlockLikeEntity block : entries.values()) { + if (block != lander) { + if (success) { + block.cease(); + } else { + World world = block.world; + BlockState state = block.getBlockState(); + BlockPos pos = block.getBlockPos(); + + // If the block has been set already, remove it. We want this BLE to break. + // This is imperfect - if the block lands on a grass plant, say, then + // the grass plant is already gone. But this should prevent duplications. + if (world.getBlockState(pos).isOf(state.getBlock())) { + world.removeBlock(pos, false); + } + block.breakApart(); + } + } + block.dropItem = false; + } + this.remove(); + } + + public BlockLikeEntity getMasterBlock() { + if (entries.containsKey(Vec3i.ZERO)) { + return entries.get(Vec3i.ZERO); + } else { + return entries.values().iterator().next(); + } + } + + private void init() { + structures.add(this); + } + + public void remove() { + structures.remove(this); + } + + /** + * A builder intended to aid the creation of {@link BlockLikeSet}s. + */ + @SuppressWarnings("unused") + public static class Builder { + protected final Map entries; + protected final BlockPos origin; + + /** + * @param origin The position of the first block in the {@link BlockLikeSet}. + */ + public Builder(BlockPos origin) { + this.origin = origin; + this.entries = new HashMap<>(2); + } + + /** + * @param entity The BlockLikeEntity to add to the {@link BlockLikeSet}. + * If there has already been an entity added at that location, + * this entity will be ignored and not added. + */ + public Builder add(BlockLikeEntity entity){ + BlockPos pos = entity.getBlockPos(); + if (!isAlreadyInSet(pos)) { + this.entries.put(pos.subtract(origin), entity); + } + return this; + } + + /** + * Allows one to add to a {@link BlockLikeSet} only if a certain condition is met. + * The predicate acts on an immutable copy of the entries so far. + * @param entity The entity that should be added to the {@link BlockLikeSet}. + * @param predicate A {@link Predicate} to test whether the block should be added. + */ + public Builder addIf(BlockLikeEntity entity, Predicate> predicate){ + if (predicate.test(Map.copyOf(entries))){ + return this.add(entity); + } + return this; + } + + /** + * @return The size of the {@link BlockLikeSet} so far. + */ + public int size(){ + return entries.size(); + } + + /** + * @return The {@link BlockLikeSet} that has been built. + */ + public BlockLikeSet build(){ + return new BlockLikeSet(entries); + } + + /** + * @param pos The position of the block to test + * @return Whether the given block is already in the set. + */ + public boolean isAlreadyInSet(BlockPos pos) { + return this.entries.containsKey(pos.subtract(origin)); + } + } +} diff --git a/src/main/java/net/id/paradiselost/api/FloatingBlockHelper.java b/src/main/java/net/id/paradiselost/api/FloatingBlockHelper.java index b68002b63..20196bc33 100644 --- a/src/main/java/net/id/paradiselost/api/FloatingBlockHelper.java +++ b/src/main/java/net/id/paradiselost/api/FloatingBlockHelper.java @@ -4,14 +4,12 @@ import net.id.paradiselost.entities.util.FloatingBlockHelperImpls; import net.id.paradiselost.items.tools.base_tools.GravityWandItem; import net.id.paradiselost.tag.ParadiseLostBlockTags; -import net.id.incubus_core.blocklikeentities.api.BlockLikeEntity; -import net.id.incubus_core.blocklikeentities.api.BlockLikeSet; import net.minecraft.block.BlockState; import net.minecraft.block.PistonBlock; import net.minecraft.block.piston.PistonHandler; import net.minecraft.item.Item; import net.minecraft.item.ItemUsageContext; -import net.minecraft.tag.BlockTags; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.math.*; import net.minecraft.world.World; diff --git a/src/main/java/net/id/paradiselost/blocks/FloatingBlock.java b/src/main/java/net/id/paradiselost/blocks/FloatingBlock.java index 97013c932..43723eee3 100644 --- a/src/main/java/net/id/paradiselost/blocks/FloatingBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/FloatingBlock.java @@ -4,6 +4,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.OreBlock; +import net.minecraft.block.RedstoneOreBlock; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -13,7 +14,7 @@ import net.minecraft.world.WorldAccess; @SuppressWarnings("deprecation") -public class FloatingBlock extends OreBlock { +public class FloatingBlock extends RedstoneOreBlock { private final boolean powered; public FloatingBlock(boolean powered, Settings properties, UniformIntProvider experienceDropped) { diff --git a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostGrassBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostGrassBlock.java index 4fd03418c..ee1f9f8ca 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostGrassBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostGrassBlock.java @@ -11,6 +11,7 @@ import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.BlockView; import net.minecraft.world.World; +import net.minecraft.world.WorldView; import net.minecraft.world.gen.feature.ConfiguredFeature; import net.minecraft.world.gen.feature.PlacedFeature; import net.minecraft.world.gen.feature.RandomPatchFeatureConfig; @@ -23,7 +24,7 @@ public ParadiseLostGrassBlock(Settings settings) { } @Override - public boolean isFertilizable(BlockView world, BlockPos pos, BlockState state, boolean isClient) { + public boolean isFertilizable(WorldView world, BlockPos pos, BlockState state, boolean isClient) { return world.getBlockState(pos.up()).isAir(); } diff --git a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostMushroomBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostMushroomBlock.java index ffc11653a..940702d37 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostMushroomBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostMushroomBlock.java @@ -3,11 +3,11 @@ import net.minecraft.block.BlockState; import net.minecraft.block.MushroomPlantBlock; import net.minecraft.block.ShapeContext; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.server.world.ServerWorld; -import net.minecraft.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; -import net.minecraft.util.registry.RegistryEntry; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; @@ -20,7 +20,7 @@ public class ParadiseLostMushroomBlock extends MushroomPlantBlock { private final HangType type; - public ParadiseLostMushroomBlock(Settings settings, Supplier>> feature, HangType type) { + public ParadiseLostMushroomBlock(Settings settings, RegistryKey> feature, HangType type) { super(settings, feature); this.type = type; } @@ -46,11 +46,6 @@ public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos po return VoxelShapes.fullCube(); } - @Override - public boolean isTranslucent(BlockState state, BlockView world, BlockPos pos) { - return true; - } - @Override public boolean trySpawningBigMushroom(ServerWorld serverWorld, BlockPos pos, BlockState state, Random random) { return false; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostWallMushroomBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostWallMushroomBlock.java index 716eadae0..6a14f8c28 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostWallMushroomBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/ParadiseLostWallMushroomBlock.java @@ -3,13 +3,13 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.item.ItemPlacementContext; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.state.StateManager; import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.Properties; -import net.minecraft.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.BlockView; import net.minecraft.world.WorldView; import net.minecraft.world.gen.feature.ConfiguredFeature; @@ -21,7 +21,7 @@ public class ParadiseLostWallMushroomBlock extends ParadiseLostMushroomBlock { public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - public ParadiseLostWallMushroomBlock(Settings settings, Supplier>> feature) { + public ParadiseLostWallMushroomBlock(Settings settings, RegistryKey> feature) { super(settings, feature, ParadiseLostMushroomBlock.HangType.WALL); } @@ -40,7 +40,7 @@ protected boolean canPlantOnTop(BlockState floor, BlockView world, BlockPos pos) @Override public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) { - return getDefaultState().with(FACING, ctx.getPlayerFacing().getOpposite()); + return getDefaultState().with(FACING, ctx.getPlayerLookDirection().getOpposite()); } @Override diff --git a/src/main/java/net/id/paradiselost/blocks/natural/cloud/GoldenParadiseLostCloudBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/cloud/GoldenParadiseLostCloudBlock.java index 5a9cf63ec..589f57c76 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/cloud/GoldenParadiseLostCloudBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/cloud/GoldenParadiseLostCloudBlock.java @@ -5,7 +5,7 @@ import net.minecraft.block.Material; import net.minecraft.block.ShapeContext; import net.minecraft.entity.Entity; -import net.minecraft.tag.BlockTags; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/cloud/PinkParadiseLostCloudBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/cloud/PinkParadiseLostCloudBlock.java deleted file mode 100644 index bc3a12cb2..000000000 --- a/src/main/java/net/id/paradiselost/blocks/natural/cloud/PinkParadiseLostCloudBlock.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.id.paradiselost.blocks.natural.cloud; - -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.particle.DustParticleEffect; -import net.minecraft.particle.ParticleEffect; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3f; -import net.minecraft.world.World; - -public class PinkParadiseLostCloudBlock extends ParadiseLostCloudBlock { - - private static final ParticleEffect pinkFluff = new DustParticleEffect(new Vec3f(0.89F, 0.65F, 0.9F), 1F); - - public PinkParadiseLostCloudBlock(Settings properties) { - super(properties); - } - - @Override - public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { - super.onEntityCollision(state, world, pos, entity); - if (!world.isClient() && entity instanceof LivingEntity) { - if (world.getTime() % 20 == 0) { - ((LivingEntity) entity).heal(1F); - for (int i = world.getRandom().nextInt(3); i <= 5; i++) { - double offX = (world.getRandom().nextDouble() * entity.getWidth()) - (entity.getWidth() / 2); - double offZ = (world.getRandom().nextDouble() * entity.getWidth()) - (entity.getWidth() / 2); - double offY = world.getRandom().nextDouble() * entity.getHeight(); - ((ServerWorld) world).spawnParticles(pinkFluff, entity.getX() + offX, entity.getY() + offY, entity.getZ() + offZ, 3, 0, 0, 0, 1); - } - } - double offX = (world.getRandom().nextDouble() * entity.getWidth()) - (entity.getWidth() / 2); - double offZ = (world.getRandom().nextDouble() * entity.getWidth()) - (entity.getWidth() / 2); - double offY = world.getRandom().nextDouble() * entity.getHeight(); - ((ServerWorld) world).spawnParticles(pinkFluff, entity.getX() + offX, entity.getY() + offY, entity.getZ() + offZ, 1, 0, 0, 0, 0.1); - } - } -} diff --git a/src/main/java/net/id/paradiselost/blocks/natural/crop/FlaxCropBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/crop/FlaxCropBlock.java index e7b3341af..c512c0ec3 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/crop/FlaxCropBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/crop/FlaxCropBlock.java @@ -1,14 +1,13 @@ package net.id.paradiselost.blocks.natural.crop; -import net.id.incubus_core.block.TallCropBlock; import net.id.paradiselost.items.ParadiseLostItems; import net.id.paradiselost.tag.ParadiseLostBlockTags; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.enums.DoubleBlockHalf; import net.minecraft.item.ItemConvertible; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.server.world.ServerWorld; -import net.minecraft.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/crop/TallCropBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/crop/TallCropBlock.java new file mode 100644 index 000000000..08ea15d31 --- /dev/null +++ b/src/main/java/net/id/paradiselost/blocks/natural/crop/TallCropBlock.java @@ -0,0 +1,213 @@ +package net.id.paradiselost.blocks.natural.crop; + +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.enums.DoubleBlockHalf; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.EnumProperty; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.*; +import org.jetbrains.annotations.Nullable; + +/** + * A crop block that is two blocks tall. + * This class is fully usable on its own, but it is recommended to extend it. + */ +@SuppressWarnings("unused") +public class TallCropBlock extends CropBlock { + public static final EnumProperty HALF = Properties.DOUBLE_BLOCK_HALF; + public final int lastSingleBlockAge; + + /** + * @param lastSingleBlockAge The highest age for which this block is one block tall. + */ + // For PL flax, lastSingleBlockAge is 3. + public TallCropBlock(Settings settings, int lastSingleBlockAge) { + super(settings); + this.lastSingleBlockAge = lastSingleBlockAge; + } + + @Override + public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random){ + this.tryGrow(state, world, pos, random, 25F); + } + + @Override + public void applyGrowth(World world, BlockPos pos, BlockState state) { + if (state.get(HALF) == DoubleBlockHalf.UPPER) { + pos = pos.down(); + state = world.getBlockState(pos); + } + if (!state.isOf(this)){ + return; + } + int newAge = this.getAge(state) + this.getGrowthAmount(world); + int maxAge = this.getMaxAge(); + if (newAge > maxAge) { + newAge = maxAge; + } + + if (newAge > this.lastSingleBlockAge && canGrowUp(world, pos, state, newAge)) { + world.setBlockState(pos, this.withAge(newAge), Block.NOTIFY_LISTENERS); + world.setBlockState(pos.up(), this.withAgeAndHalf(newAge, DoubleBlockHalf.UPPER), Block.NOTIFY_LISTENERS); + } else { + world.setBlockState(pos, this.withAge(Math.min(newAge, lastSingleBlockAge)), Block.NOTIFY_LISTENERS); + } + } + + private boolean canGrowUp(World world, BlockPos pos, BlockState state, int age) { + return world.getBlockState(pos.up()).isOf(this) || world.getBlockState(pos.up()).getMaterial().isReplaceable(); + } + + /** + * Tries to grow the crop. Call me in randomTick(). + * Will not do anything if the block state is upper. + * + * @param upperBound The inverse of the probability of the crop growing with zero moisture. + *
E.g. If upperBound is 25F, the crop with no moisture will grow about 1 in every 25 attempts. + * The more moisture, the more likely. + */ + @SuppressWarnings("SameParameterValue") + protected void tryGrow(BlockState state, ServerWorld world, BlockPos pos, Random random, float upperBound) { + if (state.get(HALF) == DoubleBlockHalf.UPPER) return; + + if (world.getBaseLightLevel(pos, 0) >= 9) { + int age = this.getAge(state); + if (age < this.getMaxAge()) { + float moisture = getAvailableMoisture(this, world, pos); + // More likely if there's more moisture + if (random.nextInt((int) (upperBound / moisture) + 1) == 0) { + if (age >= Block.NOTIFY_LISTENERS) { + if (world.getBlockState(pos.up()).isOf(this) || world.getBlockState(pos.up()).getMaterial().isReplaceable()) { + world.setBlockState(pos, this.withAge(age + 1), Block.NOTIFY_LISTENERS); + world.setBlockState(pos.up(), this.withAgeAndHalf(age + 1, DoubleBlockHalf.UPPER), Block.NOTIFY_LISTENERS); + } + } else { + world.setBlockState(pos, this.withAge(age + 1), Block.NOTIFY_LISTENERS); + } + } + } + } + } + + /** + * Returns the bottom block state for the given age. + */ + @Override + public BlockState withAge(int age) { + return this.withAgeAndHalf(age, DoubleBlockHalf.LOWER); + } + + public BlockState withAgeAndHalf(int age, DoubleBlockHalf half) { + return this.getDefaultState().with(this.getAgeProperty(), age).with(HALF, half); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(HALF).add(AGE); + } + + @Override + public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) { + if (state.get(HALF) != DoubleBlockHalf.UPPER) { + BlockPos blockPos = pos.down(); + return this.canPlantOnTop(world.getBlockState(blockPos), world, blockPos); + } else { + BlockState blockState = world.getBlockState(pos.down()); + return blockState.isOf(this) && blockState.get(HALF) == DoubleBlockHalf.LOWER && blockState.get(AGE) > this.lastSingleBlockAge; + } + } + + protected DoubleBlockHalf getHalf(BlockState state) { + return state.get(HALF); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + if (state.get(HALF) == DoubleBlockHalf.LOWER) { + if (state.get(AGE) <= this.lastSingleBlockAge) { + return super.getOutlineShape(state, world, pos, context); + } else { + // Fill in the bottom block if the plant is two-tall + return Block.createCuboidShape(0, 0, 0,16, 16, 16); + } + } else { + return super.getOutlineShape(this.withAge(state.get(AGE) - this.lastSingleBlockAge - 1), world, pos, context); + } + } + + // below code is (mostly) copied from TallPlantBlock + + public static BlockState withWaterloggedState(WorldView world, BlockPos pos, BlockState state) { + return state.contains(Properties.WATERLOGGED) ? state.with(Properties.WATERLOGGED, world.isWater(pos)) : state; + } + + public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + DoubleBlockHalf doubleBlockHalf = state.get(HALF); + if (direction.getAxis() == Direction.Axis.Y && doubleBlockHalf == DoubleBlockHalf.LOWER == (direction == Direction.UP)) { + return (state.get(AGE) <= lastSingleBlockAge || neighborState.isOf(this) && neighborState.get(HALF) != doubleBlockHalf) ? state : Blocks.AIR.getDefaultState(); + } else { + return doubleBlockHalf == DoubleBlockHalf.LOWER && direction == Direction.DOWN && !state.canPlaceAt(world, pos) ? Blocks.AIR.getDefaultState() : super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos); + } + } + + @Override + @Nullable + public BlockState getPlacementState(ItemPlacementContext ctx) { + BlockPos blockPos = ctx.getBlockPos(); + World world = ctx.getWorld(); + return blockPos.getY() < world.getTopY() - 1 && world.getBlockState(blockPos.up()).canReplace(ctx) ? this.withAgeAndHalf(0, DoubleBlockHalf.LOWER) : null; + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { + // Place the other half + if (state.get(HALF) == DoubleBlockHalf.UPPER) { + world.setBlockState(pos.down(), this.withAgeAndHalf(state.get(AGE), DoubleBlockHalf.LOWER), Block.NOTIFY_ALL); + } else { + if (state.get(AGE) > this.lastSingleBlockAge) { + world.setBlockState(pos.up(), this.withAgeAndHalf(state.get(AGE), DoubleBlockHalf.UPPER), Block.NOTIFY_ALL); + } + } + } + + protected static void onBreakInCreative(World world, BlockPos pos, BlockState state, PlayerEntity player) { + if (state.get(HALF) == DoubleBlockHalf.UPPER) { + // Break the other half + BlockPos blockPos = pos.down(); + BlockState blockState = world.getBlockState(blockPos); + if (blockState.isOf(state.getBlock()) && blockState.get(HALF) == DoubleBlockHalf.LOWER) { + BlockState blockState2 = blockState.contains(Properties.WATERLOGGED) && blockState.get(Properties.WATERLOGGED) ? Blocks.WATER.getDefaultState() : Blocks.AIR.getDefaultState(); + world.setBlockState(blockPos, blockState2, Block.SKIP_DROPS | Block.NOTIFY_ALL); + world.syncWorldEvent(player, WorldEvents.BLOCK_BROKEN, blockPos, Block.getRawIdFromState(blockState)); + } + } + } + + @Override + public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + if (!world.isClient) { + if (player.isCreative()) { + onBreakInCreative(world, pos, state, player); + } else { + dropStacks(state, world, pos, null, player, player.getMainHandStack()); + } + } + + super.onBreak(world, pos, state, player); + } + + @Override + public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { + super.afterBreak(world, player, pos, Blocks.AIR.getDefaultState(), blockEntity, stack); + } +} diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/GroundcoverBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/GroundcoverBlock.java index cbbb2a20e..20a3305e3 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/GroundcoverBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/GroundcoverBlock.java @@ -7,7 +7,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; @@ -20,7 +20,7 @@ public class GroundcoverBlock extends ParadiseLostBrushBlock { private final double slowdown; public GroundcoverBlock(Settings settings, double slowdown) { - super(settings.offsetType(OffsetType.NONE)); + super(settings.offset(OffsetType.NONE)); this.slowdown = slowdown; } diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostBrushBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostBrushBlock.java index af8591e00..92d29609d 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostBrushBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostBrushBlock.java @@ -6,8 +6,8 @@ import net.minecraft.block.BlockState; import net.minecraft.block.FernBlock; import net.minecraft.block.TallPlantBlock; +import net.minecraft.registry.tag.TagKey; import net.minecraft.server.world.ServerWorld; -import net.minecraft.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.random.Random; @@ -19,7 +19,7 @@ public class ParadiseLostBrushBlock extends FernBlock { private final boolean override; public ParadiseLostBrushBlock(Settings settings) { - this(settings.offsetType(OffsetType.XZ), ParadiseLostBlockTags.GENERIC_VALID_GROUND, false); + this(settings.offset(OffsetType.XZ), ParadiseLostBlockTags.GENERIC_VALID_GROUND, false); } public ParadiseLostBrushBlock(Settings settings, TagKey validFloors, boolean override) { diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostHangingMushroomPlantBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostHangingMushroomPlantBlock.java index 3189d4541..3bc01cb87 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostHangingMushroomPlantBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostHangingMushroomPlantBlock.java @@ -3,7 +3,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ShapeContext; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.BlockView; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostMushroomPlantBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostMushroomPlantBlock.java index 91031424e..7750c17ae 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostMushroomPlantBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostMushroomPlantBlock.java @@ -2,7 +2,7 @@ import net.minecraft.block.*; import net.minecraft.server.world.ServerWorld; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.BlockView; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostTallBrushBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostTallBrushBlock.java index 674f5311e..1a2b18072 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostTallBrushBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/ParadiseLostTallBrushBlock.java @@ -4,7 +4,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.TallPlantBlock; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockView; diff --git a/src/main/java/net/id/paradiselost/blocks/natural/plant/WallClingingPlantBlock.java b/src/main/java/net/id/paradiselost/blocks/natural/plant/WallClingingPlantBlock.java index 43b02fe87..636d69c9c 100644 --- a/src/main/java/net/id/paradiselost/blocks/natural/plant/WallClingingPlantBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/natural/plant/WallClingingPlantBlock.java @@ -8,7 +8,7 @@ import net.minecraft.state.StateManager; import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.Properties; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; diff --git a/src/main/java/net/id/paradiselost/blocks/util/SpreadableParadiseLostBlock.java b/src/main/java/net/id/paradiselost/blocks/util/SpreadableParadiseLostBlock.java index 7897f3ef9..0d27c1155 100644 --- a/src/main/java/net/id/paradiselost/blocks/util/SpreadableParadiseLostBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/util/SpreadableParadiseLostBlock.java @@ -5,8 +5,8 @@ import net.minecraft.block.Blocks; import net.minecraft.block.SnowBlock; import net.minecraft.block.SnowyBlock; +import net.minecraft.registry.tag.FluidTags; import net.minecraft.server.world.ServerWorld; -import net.minecraft.tag.FluidTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.random.Random; diff --git a/src/main/java/net/id/paradiselost/client/rendering/entity/BlockLikeEntityRenderer.java b/src/main/java/net/id/paradiselost/client/rendering/entity/BlockLikeEntityRenderer.java new file mode 100644 index 000000000..5e3bf6561 --- /dev/null +++ b/src/main/java/net/id/paradiselost/client/rendering/entity/BlockLikeEntityRenderer.java @@ -0,0 +1,55 @@ +package net.id.paradiselost.client.rendering.entity; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.id.paradiselost.api.BlockLikeEntity; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.*; +import net.minecraft.client.render.block.BlockRenderManager; +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; + +@SuppressWarnings("unused") +@Environment(EnvType.CLIENT) +public class BlockLikeEntityRenderer extends EntityRenderer { + private final Random random = Random.create(); + + public BlockLikeEntityRenderer(EntityRendererFactory.Context renderManager) { + super(renderManager); + this.shadowRadius = 0.5F; + } + + @Override + public void render(BlockLikeEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { + BlockState blockState = entity.getBlockState(); + + if (blockState.getRenderType() == BlockRenderType.MODEL) { + World world = entity.getWorldObj(); + + if (blockState != world.getBlockState(new BlockPos(entity.getBlockPos())) && blockState.getRenderType() != BlockRenderType.INVISIBLE) { + matrices.push(); + + BlockPos blockpos = new BlockPos(new BlockPos(entity.getBlockPos())); + matrices.translate(-0.5, 0.0, -0.5); + BlockRenderManager blockRenderManager = MinecraftClient.getInstance().getBlockRenderManager(); + blockRenderManager.getModelRenderer().render(world, blockRenderManager.getModel(blockState), blockState, blockpos, matrices, vertexConsumers.getBuffer(RenderLayers.getMovingBlockLayer(blockState)), false, random, blockState.getRenderingSeed(entity.getOrigin()), OverlayTexture.DEFAULT_UV); + matrices.pop(); + super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public Identifier getTexture(BlockLikeEntity entityIn) { + return SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE; + } +} diff --git a/src/main/java/net/id/paradiselost/entities/block/FloatingBlockEntity.java b/src/main/java/net/id/paradiselost/entities/block/FloatingBlockEntity.java index e98b0273e..3d28c6d6b 100644 --- a/src/main/java/net/id/paradiselost/entities/block/FloatingBlockEntity.java +++ b/src/main/java/net/id/paradiselost/entities/block/FloatingBlockEntity.java @@ -1,9 +1,9 @@ package net.id.paradiselost.entities.block; +import net.id.paradiselost.api.BlockLikeEntity; import net.id.paradiselost.api.FloatingBlockHelper; import net.id.paradiselost.entities.ParadiseLostEntityTypes; import net.id.paradiselost.tag.ParadiseLostBlockTags; -import net.id.incubus_core.blocklikeentities.api.BlockLikeEntity; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.FallingBlock; @@ -11,7 +11,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.MovementType; import net.minecraft.nbt.NbtCompound; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; diff --git a/src/main/java/net/id/paradiselost/entities/block/SliderEntity.java b/src/main/java/net/id/paradiselost/entities/block/SliderEntity.java index cf416a48e..9ccf2ce8c 100644 --- a/src/main/java/net/id/paradiselost/entities/block/SliderEntity.java +++ b/src/main/java/net/id/paradiselost/entities/block/SliderEntity.java @@ -1,9 +1,9 @@ package net.id.paradiselost.entities.block; import net.fabricmc.fabric.api.util.NbtType; +import net.id.paradiselost.api.BlockLikeEntity; import net.id.paradiselost.blocks.ParadiseLostBlocks; import net.id.paradiselost.entities.ParadiseLostEntityTypes; -import net.id.incubus_core.blocklikeentities.api.BlockLikeEntity; import net.minecraft.block.BlockState; import net.minecraft.entity.EntityType; import net.minecraft.entity.MovementType; diff --git a/src/main/java/net/id/paradiselost/entities/util/FloatingBlockHelperImpls.java b/src/main/java/net/id/paradiselost/entities/util/FloatingBlockHelperImpls.java index 46a7bcd68..fa4d2376b 100644 --- a/src/main/java/net/id/paradiselost/entities/util/FloatingBlockHelperImpls.java +++ b/src/main/java/net/id/paradiselost/entities/util/FloatingBlockHelperImpls.java @@ -1,9 +1,9 @@ package net.id.paradiselost.entities.util; +import net.id.paradiselost.api.BlockLikeSet; import net.id.paradiselost.api.FloatingBlockHelper; import net.id.paradiselost.entities.block.FloatingBlockEntity; import net.id.paradiselost.tag.ParadiseLostBlockTags; -import net.id.incubus_core.blocklikeentities.api.BlockLikeSet; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.FallingBlock; diff --git a/src/main/java/net/id/paradiselost/entities/util/PostTickEntity.java b/src/main/java/net/id/paradiselost/entities/util/PostTickEntity.java new file mode 100644 index 000000000..d38430c18 --- /dev/null +++ b/src/main/java/net/id/paradiselost/entities/util/PostTickEntity.java @@ -0,0 +1,8 @@ +package net.id.paradiselost.entities.util; + +/** + * An interface for entities that need to be ticked after the main tick. + */ +public interface PostTickEntity { + void incubus_Concern$postTick(); +} \ No newline at end of file diff --git a/src/main/java/net/id/paradiselost/tag/ParadiseLostBlockTags.java b/src/main/java/net/id/paradiselost/tag/ParadiseLostBlockTags.java index 16004906d..881ca2ebe 100644 --- a/src/main/java/net/id/paradiselost/tag/ParadiseLostBlockTags.java +++ b/src/main/java/net/id/paradiselost/tag/ParadiseLostBlockTags.java @@ -2,7 +2,8 @@ import net.id.paradiselost.ParadiseLost; import net.minecraft.block.Block; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; public class ParadiseLostBlockTags { diff --git a/src/main/java/net/id/paradiselost/tag/ParadiseLostEntityTypeTags.java b/src/main/java/net/id/paradiselost/tag/ParadiseLostEntityTypeTags.java index 7f40b7173..f59fdbddb 100644 --- a/src/main/java/net/id/paradiselost/tag/ParadiseLostEntityTypeTags.java +++ b/src/main/java/net/id/paradiselost/tag/ParadiseLostEntityTypeTags.java @@ -2,7 +2,7 @@ import net.id.paradiselost.ParadiseLost; import net.minecraft.entity.EntityType; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; public class ParadiseLostEntityTypeTags { diff --git a/src/main/java/net/id/paradiselost/tag/ParadiseLostFluidTags.java b/src/main/java/net/id/paradiselost/tag/ParadiseLostFluidTags.java index 36c36703d..c3d264ea9 100644 --- a/src/main/java/net/id/paradiselost/tag/ParadiseLostFluidTags.java +++ b/src/main/java/net/id/paradiselost/tag/ParadiseLostFluidTags.java @@ -2,7 +2,7 @@ import net.id.paradiselost.ParadiseLost; import net.minecraft.fluid.Fluid; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; public class ParadiseLostFluidTags { diff --git a/src/main/java/net/id/paradiselost/tag/ParadiseLostItemTags.java b/src/main/java/net/id/paradiselost/tag/ParadiseLostItemTags.java index 54852cb9d..d0976c32a 100644 --- a/src/main/java/net/id/paradiselost/tag/ParadiseLostItemTags.java +++ b/src/main/java/net/id/paradiselost/tag/ParadiseLostItemTags.java @@ -2,7 +2,7 @@ import net.id.paradiselost.ParadiseLost; import net.minecraft.item.Item; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; public class ParadiseLostItemTags { diff --git a/src/main/java/net/id/paradiselost/tag/ParadiseLostStructureTags.java b/src/main/java/net/id/paradiselost/tag/ParadiseLostStructureTags.java index 988f9e76a..87ca9fd5b 100644 --- a/src/main/java/net/id/paradiselost/tag/ParadiseLostStructureTags.java +++ b/src/main/java/net/id/paradiselost/tag/ParadiseLostStructureTags.java @@ -1,7 +1,7 @@ package net.id.paradiselost.tag; import net.id.paradiselost.ParadiseLost; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; diff --git a/src/main/java/net/id/paradiselost/world/feature/structure/ParadiseLostStructureFeatures.java b/src/main/java/net/id/paradiselost/world/feature/structure/ParadiseLostStructureFeatures.java index a06b2dadb..7b160acd4 100644 --- a/src/main/java/net/id/paradiselost/world/feature/structure/ParadiseLostStructureFeatures.java +++ b/src/main/java/net/id/paradiselost/world/feature/structure/ParadiseLostStructureFeatures.java @@ -3,7 +3,7 @@ import net.id.paradiselost.world.feature.structure.generator.AurelTowerGenerator; import net.id.paradiselost.world.feature.structure.generator.WellGenerator; import net.minecraft.structure.StructurePieceType; -import net.minecraft.tag.TagKey; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.registry.Registry; import net.minecraft.world.gen.structure.Structure; import net.minecraft.world.gen.structure.StructureType; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b7f28dc23..1c557d10e 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -7,19 +7,15 @@ "license": "MIT", "authors": [ "Immortal Devs - parent organization", - "kalucky0 - head of project", + "kalucky0 - head of organization", + "24Chrome - project lead", "Azazelthedemonlord - lead designer", - "24Chrome - lead artist", "Jack Papel - lead developer", "sunsette - lead sound designer", - "CDAGaming - developer / very based person", + "CDAGaming - developer", "SollyW - developer", "gudenau - developer", - "Kyrptonaught - developer", - "yelldow - sound designer / composer", - "Brandon Pearce (kingbdogz_) - GG founder / Aether creator", - "Oscar Payn (ozzAR0th ) - GG head", - "Hugo Payn (DevilBringer) - GG design lead" + "Kyrptonaught - developer" ], "contact": { "homepage": "https://immortaldevs.net/paradise-lost",