diff --git a/src/main/java/io/github/cottonmc/templates/api/TemplateInteractionUtil.java b/src/main/java/io/github/cottonmc/templates/api/TemplateInteractionUtil.java index e62ea53..fd99c1e 100644 --- a/src/main/java/io/github/cottonmc/templates/api/TemplateInteractionUtil.java +++ b/src/main/java/io/github/cottonmc/templates/api/TemplateInteractionUtil.java @@ -27,16 +27,19 @@ import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; public class TemplateInteractionUtil { - public static final IntProperty LIGHT = IntProperty.of("light", 0, 15); - public static final BooleanProperty REDSTONE = BooleanProperty.of("redstone"); + public static final IntProperty LIGHT = IntProperty.of("templates_light", 0, 15); + public static final BooleanProperty REDSTONE = BooleanProperty.of("templates_redstone"); + public static final BooleanProperty SOLID = BooleanProperty.of("templates_solid"); public static StateManager.Builder appendProperties(StateManager.Builder builder) { - return builder.add(LIGHT, REDSTONE); + return builder.add(LIGHT, REDSTONE, SOLID); } public static AbstractBlock.Settings makeSettings() { @@ -48,7 +51,7 @@ public class TemplateInteractionUtil { } public static BlockState setDefaultStates(BlockState in) { - return in.with(LIGHT, 0).with(REDSTONE, false); + return in.with(LIGHT, 0).with(REDSTONE, false).with(SOLID, true); } public static ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { @@ -77,6 +80,16 @@ public class TemplateInteractionUtil { return ActionResult.SUCCESS; } + //Popped chorus fruit + if(state.contains(SOLID) && held.getItem() == Items.POPPED_CHORUS_FRUIT && state.get(SOLID) && !be.hasSpentPoppedChorus()) { + world.setBlockState(pos, state.with(SOLID, false)); + be.spentPoppedChorus(); + + if(!player.isCreative()) held.decrement(1); + world.playSound(player, pos, SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.BLOCKS, 1f, 1f); + return ActionResult.SUCCESS; + } + //Changing the theme if(held.getItem() instanceof BlockItem bi && be.getThemeState().getBlock() == Blocks.AIR) { Block block = bi.getBlock(); @@ -108,6 +121,7 @@ public class TemplateInteractionUtil { if(template.hasSpentRedstoneTorch()) drops.add(new ItemStack(Items.REDSTONE_TORCH)); if(template.hasSpentGlowstoneDust()) drops.add(new ItemStack(Items.GLOWSTONE_DUST)); + if(template.hasSpentPoppedChorus()) drops.add(new ItemStack(Items.POPPED_CHORUS_FRUIT)); ItemScatterer.spawn(world, pos, drops); } @@ -122,6 +136,10 @@ public class TemplateInteractionUtil { } } + public static @Nullable VoxelShape getCollisionShape(BlockState state) { + return state.contains(SOLID) && !state.get(SOLID) ? VoxelShapes.empty() : null; + } + public static boolean emitsRedstonePower(BlockState state) { return state.contains(REDSTONE) ? state.get(REDSTONE) : false; } diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java index 254bee0..2a33f15 100644 --- a/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java @@ -1,9 +1,11 @@ package io.github.cottonmc.templates.block; +import com.google.common.base.MoreObjects; import io.github.cottonmc.templates.api.TemplateInteractionUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -14,6 +16,7 @@ import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.BlockView; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -49,6 +52,11 @@ public abstract class TemplateBlock extends Block implements BlockEntityProvider super.onPlaced(world, pos, state, placer, stack); } + @Override + public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { + return MoreObjects.firstNonNull(TemplateInteractionUtil.getCollisionShape(state), super.getCollisionShape(state, view, pos, ctx)); + } + @Override public boolean emitsRedstonePower(BlockState state) { return TemplateInteractionUtil.emitsRedstonePower(state); diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java index 9d4720d..dbb9d1e 100644 --- a/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java @@ -1,10 +1,12 @@ package io.github.cottonmc.templates.block; +import com.google.common.base.MoreObjects; import io.github.cottonmc.templates.Templates; import io.github.cottonmc.templates.api.TemplateInteractionUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; import net.minecraft.block.SlabBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.LivingEntity; @@ -16,6 +18,7 @@ import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.BlockView; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -53,6 +56,11 @@ public class TemplateSlabBlock extends SlabBlock implements BlockEntityProvider TemplateInteractionUtil.onPlaced(world, pos, state, placer, stack); } + @Override + public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { + return MoreObjects.firstNonNull(TemplateInteractionUtil.getCollisionShape(state), super.getCollisionShape(state, view, pos, ctx)); + } + @Override public boolean emitsRedstonePower(BlockState state) { return TemplateInteractionUtil.emitsRedstonePower(state); diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java index e392679..5a9931d 100644 --- a/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java @@ -1,6 +1,8 @@ package io.github.cottonmc.templates.block; +import com.google.common.base.MoreObjects; import io.github.cottonmc.templates.Templates; +import io.github.cottonmc.templates.api.TemplateInteractionUtil; import io.github.cottonmc.templates.util.StairShapeMaker; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -67,11 +69,11 @@ public class TemplateSlopeBlock extends TemplateBlock { @Override public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { - return shapes[shapeIndex(state.get(FACING), state.get(HALF))]; + return MoreObjects.firstNonNull(super.getCollisionShape(state, view, pos, ctx), shapes[shapeIndex(state.get(FACING), state.get(HALF))]); } @Override public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { - return getCollisionShape(state, view, pos, ctx); + return shapes[shapeIndex(state.get(FACING), state.get(HALF))]; } } diff --git a/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java b/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java index 129565c..7e0ab78 100644 --- a/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java +++ b/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java @@ -28,6 +28,7 @@ public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity //blockstate for it is a little silly, so, here you go. protected boolean spentGlowstoneDust = false; protected boolean spentRedstoneTorch = false; + protected boolean spentPoppedChorus = false; public TemplateEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -42,6 +43,7 @@ public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity renderedState = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound("BlockState")); spentGlowstoneDust = tag.getBoolean("Glowstone"); spentRedstoneTorch = tag.getBoolean("Redstone"); + spentPoppedChorus = tag.getBoolean("Chorus"); //Force a chunk remesh on the client if the displayed blockstate has changed if(world != null && world.isClient && !Objects.equals(lastRenderedState, renderedState)) { @@ -55,6 +57,7 @@ public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity tag.put("BlockState", NbtHelper.fromBlockState(renderedState)); tag.putBoolean("Glowstone", spentGlowstoneDust); tag.putBoolean("Redstone", spentRedstoneTorch); + tag.putBoolean("Chorus", spentPoppedChorus); } @Nullable @@ -99,4 +102,13 @@ public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity spentRedstoneTorch = true; markDirty(); } + + public boolean hasSpentPoppedChorus() { + return spentPoppedChorus; + } + + public void spentPoppedChorus() { + spentPoppedChorus = true; + markDirty(); + } } diff --git a/src/main/java/io/github/cottonmc/templates/model/TemplateAppearanceManager.java b/src/main/java/io/github/cottonmc/templates/model/TemplateAppearanceManager.java index 3acbbb9..d16ac1b 100644 --- a/src/main/java/io/github/cottonmc/templates/model/TemplateAppearanceManager.java +++ b/src/main/java/io/github/cottonmc/templates/model/TemplateAppearanceManager.java @@ -1,6 +1,7 @@ package io.github.cottonmc.templates.model; import io.github.cottonmc.templates.TemplatesClient; +import io.github.cottonmc.templates.util.TattletaleRandom; import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; @@ -17,7 +18,6 @@ import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.random.Random; import org.jetbrains.annotations.NotNull; @@ -60,7 +60,7 @@ public class TemplateAppearanceManager { //The results are going to be the same, apart from their serialNumbers differing (= their equals & hashCode differing). //Tiny amount of wasted space in some caches if TemplateAppearances are used as a map key, then. IMO it's not a critical issue. private TemplateAppearance computeAppearance(BlockState state) { - Random rand = Random.create(); + TattletaleRandom rand = new TattletaleRandom(Random.create()); BakedModel model = MinecraftClient.getInstance().getBlockRenderManager().getModel(state); //Only for parsing vanilla quads: @@ -128,6 +128,10 @@ public class TemplateAppearanceManager { if(sprites[i] == null) sprites[i] = defaultAppearance.getParticleSprite(); } + if(rand.wasUsed) { + //System.err.println("State " + state + " makes use of a randomized model"); + } + return new ComputedApperance( sprites, bakeFlags, diff --git a/src/main/java/io/github/cottonmc/templates/util/TattletaleRandom.java b/src/main/java/io/github/cottonmc/templates/util/TattletaleRandom.java new file mode 100644 index 0000000..c2717b2 --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/util/TattletaleRandom.java @@ -0,0 +1,83 @@ +package io.github.cottonmc.templates.util; + +import net.minecraft.util.math.random.Random; +import net.minecraft.util.math.random.RandomSplitter; + +public class TattletaleRandom implements Random { + public TattletaleRandom(Random delegate) { + this.delegate = delegate; + } + + private final Random delegate; + public boolean wasUsed = false; + + public Random split() { + wasUsed = true; + return delegate.split(); + } + + public RandomSplitter nextSplitter() { + wasUsed = true; + return delegate.nextSplitter(); + } + + public void setSeed(long l) { + wasUsed = true; + delegate.setSeed(l); + } + + public int nextInt() { + wasUsed = true; + return delegate.nextInt(); + } + + public int nextInt(int i) { + wasUsed = true; + return delegate.nextInt(i); + } + + public int nextBetween(int i, int j) { + wasUsed = true; + return delegate.nextBetween(i, j); + } + + public long nextLong() { + wasUsed = true; + return delegate.nextLong(); + } + + public boolean nextBoolean() { + wasUsed = true; + return delegate.nextBoolean(); + } + + public float nextFloat() { + wasUsed = true; + return delegate.nextFloat(); + } + + public double nextDouble() { + wasUsed = true; + return delegate.nextDouble(); + } + + public double nextGaussian() { + wasUsed = true; + return delegate.nextGaussian(); + } + + public double nextTriangular(double d, double e) { + wasUsed = true; + return delegate.nextTriangular(d, e); + } + + public void skip(int i) { + wasUsed = true; + delegate.skip(i); + } + + public int nextBetweenExclusive(int i, int j) { + wasUsed = true; + return delegate.nextBetweenExclusive(i, j); + } +}