diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index a6ae1c58..dd3bf4d9 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -80,7 +80,7 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi } public boolean hasIronGut() { - return !isHuman() && this != CHANGELING; + return !isHuman(); } public boolean isUnset() { diff --git a/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java b/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java index db4d1224..339c0aac 100644 --- a/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java +++ b/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java @@ -28,6 +28,7 @@ public interface UCriteria { CustomEventCriterion.Trigger POWER_UP_HEART = CUSTOM_EVENT.createTrigger("power_up_heart"); CustomEventCriterion.Trigger SPLIT_SEA = CUSTOM_EVENT.createTrigger("split_sea"); CustomEventCriterion.Trigger RIDE_BALLOON = CUSTOM_EVENT.createTrigger("ride_balloon"); + CustomEventCriterion.Trigger CONSTRUCT_BALLOON = CUSTOM_EVENT.createTrigger("construct_balloon"); CustomEventCriterion.Trigger TELEPORT_ABOVE_WORLD = CUSTOM_EVENT.createTrigger("teleport_above_world"); static void bootstrap() { } diff --git a/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java index bc26712f..f2fa1820 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java @@ -31,7 +31,6 @@ import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; import net.minecraft.world.World; -import net.minecraft.world.WorldAccess; import net.minecraft.world.event.GameEvent; public class FancyBedBlock extends BedBlock { diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 1c45b8a8..32e48568 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -36,6 +36,7 @@ import com.minelittlepony.unicopia.item.cloud.CloudBlockItem; import com.minelittlepony.unicopia.item.group.ItemGroupRegistry; import com.minelittlepony.unicopia.server.world.UTreeGen; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.fabricmc.fabric.api.registry.CompostingChanceRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.OxidizableBlocksRegistry; import net.fabricmc.fabric.api.registry.StrippableBlockRegistry; @@ -253,6 +254,7 @@ public interface UBlocks { Block SPECTRAL_FIRE = register("spectral_fire", new SpectralFireBlock(Settings.copy(Blocks.SOUL_FIRE))); + Block WORM_BLOCK = register("worm_block", new FallingBlock(Settings.create().hardness(0.1F).resistance(0).requiresTool().sounds(BlockSoundGroup.MUD)), ItemGroups.NATURAL); EdibleBlock HAY_BLOCK = register("hay_block", new EdibleBlock(new Identifier("hay_block"), new Identifier("wheat"), true)); private static <T extends Block> T register(String name, T item) { @@ -328,6 +330,8 @@ public interface UBlocks { FlammableBlockRegistry.getDefaultInstance().add(BANANAS, 5, 20); FlammableBlockRegistry.getDefaultInstance().add(CURING_JOKE, 60, 100); + CompostingChanceRegistry.INSTANCE.add(WORM_BLOCK, 8F); + UBlockEntities.bootstrap(); EdibleBlock.bootstrap(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java index 69b372b8..baeb2f16 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java @@ -1,79 +1,115 @@ package com.minelittlepony.unicopia.block.cloud; import java.util.Map; +import java.util.function.Function; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.PillarBlock; import net.minecraft.block.ShapeContext; import net.minecraft.item.ItemPlacementContext; import net.minecraft.state.StateManager; import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; +import net.minecraft.util.BlockRotation; +import net.minecraft.util.Util; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Direction.AxisDirection; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; import net.minecraft.world.WorldAccess; public class CloudPillarBlock extends CloudBlock { - private static final BooleanProperty NORTH = Properties.NORTH; - private static final BooleanProperty SOUTH = Properties.SOUTH; + public static final EnumProperty<Direction.Axis> AXIS = Properties.AXIS; + private static final BooleanProperty TOP = Properties.NORTH; + private static final BooleanProperty BOTTOM = Properties.SOUTH; private static final Map<Direction, BooleanProperty> DIRECTION_PROPERTIES = Map.of( - Direction.UP, NORTH, - Direction.DOWN, SOUTH + Direction.UP, TOP, Direction.DOWN, BOTTOM, + Direction.SOUTH, TOP, Direction.NORTH, BOTTOM, + Direction.EAST, TOP, Direction.WEST, BOTTOM ); - - private static final VoxelShape CORE_SHAPE = Block.createCuboidShape(1, 0, 1, 15, 16, 15); - private static final VoxelShape FOOT_SHAPE = Block.createCuboidShape(0, 0, 0, 16, 5, 16); - private static final VoxelShape CAP_SHAPE = FOOT_SHAPE.offset(0, 11F / 16F, 0); - - private static final VoxelShape[] SHAPES = new VoxelShape[] { - CORE_SHAPE, - VoxelShapes.union(CORE_SHAPE, FOOT_SHAPE), - VoxelShapes.union(CORE_SHAPE, CAP_SHAPE), - VoxelShapes.union(CORE_SHAPE, FOOT_SHAPE, CAP_SHAPE) - }; - // [0,0] [0,1] - // [1,0] [1,1] + private static final Function<Direction.Axis, VoxelShape[]> SHAPES = Util.memoize(axis -> { + int[] offsets = { axis.choose(1, 0, 0), axis.choose(0, 1, 0), axis.choose(0, 0, 1) }; + float capOffset = 11F / 16F; + VoxelShape core = Block.createCuboidShape( + axis.choose(0, 1, 1), axis.choose(1, 0, 1), axis.choose(1, 1, 0), + 16 - axis.choose(0, 1, 1), 16 - axis.choose(1, 0, 1), 16 - axis.choose(1, 1, 0) + ); + VoxelShape foot = Block.createCuboidShape(0, 0, 0, 16 - (11 * offsets[0]), 16 - (11 * offsets[1]), 16 - (11 * offsets[2])); + VoxelShape cap = foot.offset(capOffset * offsets[0], capOffset * offsets[1], capOffset * offsets[2]); + return new VoxelShape[] { + core, + VoxelShapes.union(core, foot), + VoxelShapes.union(core, cap), + VoxelShapes.union(core, cap, foot) + }; + }); public CloudPillarBlock(Settings settings) { super(settings, false); - setDefaultState(getDefaultState().with(NORTH, true).with(SOUTH, true)); + setDefaultState(getDefaultState().with(TOP, true).with(BOTTOM, true).with(AXIS, Direction.Axis.Y)); } @Override protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { - builder.add(NORTH, SOUTH); + builder.add(AXIS, TOP, BOTTOM); } @Override protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, EquineContext equineContext) { - return SHAPES[(state.get(NORTH) ? 0 : 2) + (state.get(SOUTH) ? 0 : 1)]; + var axis = state.get(AXIS); + + int[] offsets = { axis.choose(1, 0, 0), axis.choose(0, 1, 0), axis.choose(0, 0, 1) }; + float capOffset = 11F / 16F; + VoxelShape core = Block.createCuboidShape( + axis.choose(0, 1, 1), axis.choose(1, 0, 1), axis.choose(1, 1, 0), + 16 - axis.choose(0, 1, 1), 16 - axis.choose(1, 0, 1), 16 - axis.choose(1, 1, 0) + ); + VoxelShape foot = Block.createCuboidShape(0, 0, 0, 16 - (11 * offsets[0]), 16 - (11 * offsets[1]), 16 - (11 * offsets[2])); + VoxelShape cap = foot.offset(capOffset * offsets[0], capOffset * offsets[1], capOffset * offsets[2]); + var temp = new VoxelShape[] { + core, + VoxelShapes.union(core, foot), + VoxelShapes.union(core, cap), + VoxelShapes.union(core, cap, foot) + }; + return temp[(state.get(TOP) ? 0 : 2) + (state.get(BOTTOM) ? 0 : 1)]; + //return SHAPES.apply(state.get(AXIS))[(state.get(TOP) ? 0 : 2) + (state.get(BOTTOM) ? 0 : 1)]; } @Override @Nullable protected BlockState getPlacementState(ItemPlacementContext placementContext, EquineContext equineContext) { BlockPos pos = placementContext.getBlockPos(); - BlockState state = super.getPlacementState(placementContext, equineContext); - for (var property : DIRECTION_PROPERTIES.entrySet()) { - state = state.with(property.getValue(), placementContext.getWorld().getBlockState(pos.offset(property.getKey())).isOf(this)); - } - return state; + Direction.Axis axis = placementContext.getSide().getAxis(); + Direction upDirection = Direction.get(AxisDirection.POSITIVE, axis); + Direction downDirection = Direction.get(AxisDirection.NEGATIVE, axis); + BlockState above = placementContext.getWorld().getBlockState(pos.offset(upDirection)); + BlockState below = placementContext.getWorld().getBlockState(pos.offset(downDirection)); + return super.getPlacementState(placementContext, equineContext) + .with(DIRECTION_PROPERTIES.get(upDirection), above.isOf(this) && above.get(AXIS) == axis) + .with(DIRECTION_PROPERTIES.get(downDirection), below.isOf(this) && below.get(AXIS) == axis) + .with(AXIS, axis); } @Deprecated @Override public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { - if (direction.getAxis() == Direction.Axis.Y) { - return state.with(DIRECTION_PROPERTIES.get(direction), neighborState.isOf(this)); + if (direction.getAxis() == state.get(AXIS)) { + return state.with(DIRECTION_PROPERTIES.get(direction), neighborState.isOf(this) && neighborState.get(AXIS) == state.get(AXIS)); } return state; } + + @Override + public BlockState rotate(BlockState state, BlockRotation rotation) { + return PillarBlock.changeRotation(state, rotation); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index 69d0ab9c..e5896bd6 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle; import com.minelittlepony.unicopia.client.particle.DiskParticle; import com.minelittlepony.unicopia.client.particle.DustCloudParticle; import com.minelittlepony.unicopia.client.particle.FloatingBubbleParticle; +import com.minelittlepony.unicopia.client.particle.FootprintParticle; import com.minelittlepony.unicopia.client.particle.GroundPoundParticle; import com.minelittlepony.unicopia.client.particle.HealthDrainParticle; import com.minelittlepony.unicopia.client.particle.LightningBoltParticle; @@ -19,7 +20,6 @@ import com.minelittlepony.unicopia.client.particle.MagicParticle; import com.minelittlepony.unicopia.client.particle.RainboomParticle; import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle; import com.minelittlepony.unicopia.client.particle.RaindropsParticle; -import com.minelittlepony.unicopia.client.particle.RunesParticle; import com.minelittlepony.unicopia.client.particle.ShockwaveParticle; import com.minelittlepony.unicopia.client.particle.SphereParticle; import com.minelittlepony.unicopia.client.render.*; @@ -54,6 +54,7 @@ import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.render.*; import net.minecraft.client.render.VertexConsumerProvider.Immediate; import net.minecraft.client.render.block.entity.BlockEntityRendererFactories; +import net.minecraft.client.render.entity.EmptyEntityRenderer; import net.minecraft.client.render.entity.FlyingItemEntityRenderer; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.json.ModelTransformationMode; @@ -68,7 +69,6 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockRenderView; -@SuppressWarnings("deprecation") public interface URenderers { BlockEntity CHEST_RENDER_ENTITY = new CloudChestBlock.TileData(BlockPos.ORIGIN, UBlocks.CLOUD_CHEST.getDefaultState()); @@ -78,10 +78,10 @@ public interface URenderers { ParticleFactoryRegistry.getInstance().register(UParticles.BUBBLE, createFactory(FloatingBubbleParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create)); + ParticleFactoryRegistry.getInstance().register(UParticles.FOOTPRINT, createFactory(FootprintParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.SHOCKWAVE, ShockwaveParticle::new); - ParticleFactoryRegistry.getInstance().register(UParticles.MAGIC_RUNES, RunesParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.DISK, DiskParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.GROUND_POUND, GroundPoundParticle::new); @@ -111,6 +111,7 @@ public interface URenderers { EntityRendererRegistry.register(UEntities.LOOT_BUG, LootBugEntityRenderer::new); EntityRendererRegistry.register(UEntities.TENTACLE, TentacleEntityRenderer::new); EntityRendererRegistry.register(UEntities.IGNOMINIOUS_BULB, IgnominiousBulbEntityRenderer::new); + EntityRendererRegistry.register(UEntities.SPECTER, EmptyEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.FANCY_BED, CloudBedBlockEntityRenderer::new); diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index e7face1d..c8d9bcff 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.client; import java.util.Optional; import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; import com.minelittlepony.common.client.gui.element.Button; import com.minelittlepony.common.event.ScreenInitCallback; @@ -33,11 +34,14 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.OpenToLanScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreens; +import net.minecraft.client.render.Camera; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.resource.ResourceType; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; public class UnicopiaClient implements ClientModInitializer { @@ -66,6 +70,20 @@ public class UnicopiaClient implements ClientModInitializer { return Optional.empty(); } + + public static Vec3d getAdjustedSoundPosition(Vec3d pos) { + PlayerCamera cam = getCamera().orElse(null); + if (cam == null) { + return pos; + } + Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); + + Vector3f rotated = pos.subtract(camera.getPos()).toVector3f(); + rotated = rotated.rotateAxis(cam.calculateRoll() * MathHelper.RADIANS_PER_DEGREE, 0, 1, 0); + + return new Vec3d(rotated).add(camera.getPos()); + } + public static Race getPreferredRace() { if (!Unicopia.getConfig().ignoreMineLP.get() && MinecraftClient.getInstance().player != null) { diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/FootprintParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/FootprintParticle.java new file mode 100644 index 00000000..32075c5e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/FootprintParticle.java @@ -0,0 +1,74 @@ +package com.minelittlepony.unicopia.client.particle; + +import org.joml.Vector3f; + +import com.minelittlepony.unicopia.particle.FootprintParticleEffect; + +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.particle.SpriteBillboardParticle; +import net.minecraft.client.particle.SpriteProvider; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public class FootprintParticle extends SpriteBillboardParticle { + // specter + + public FootprintParticle(FootprintParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) { + super(world, x, y, z, 0, 0, 0); + setVelocity(0, 0, 0); + setSprite(provider.getSprite(world.random)); + this.angle = effect.yaw() * MathHelper.RADIANS_PER_DEGREE; + this.maxAge = 1000; + this.gravityStrength = 1; + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT; + } + + @Override + public void tick() { + super.tick(); + } + + @Override + public void buildGeometry(VertexConsumer drawer, Camera camera, float tickDelta) { + Vec3d cam = camera.getPos(); + + float renderX = (float)(MathHelper.lerp(tickDelta, prevPosX, x) - cam.getX()); + float renderY = (float)(MathHelper.lerp(tickDelta, prevPosY, y) - cam.getY()); + float renderZ = (float)(MathHelper.lerp(tickDelta, prevPosZ, z) - cam.getZ()); + + Vector3f[] corners = new Vector3f[]{ + new Vector3f(-1, 0, -1), + new Vector3f(-1, 0, 1), + new Vector3f( 1, 0, 1), + new Vector3f( 1, 0, -1) + }; + for (int k = 0; k < 4; ++k) { + Vector3f corner = corners[k]; + corner.mul(0.2F); + corner.rotateAxis(angle, 0, 1, 0); + corner.add(renderX, renderY + 0.0001F, renderZ); + } + + float alpha = this.alpha * (1 - ((float)age / maxAge)); + int light = getBrightness(tickDelta); + + float minU = this.sprite.getMinU(); + float maxU = this.sprite.getMaxU(); + + float minV = this.sprite.getMinV(); + float maxV = this.sprite.getMaxV(); + + drawer.vertex(corners[0].x, corners[0].y, corners[0].z).texture(minU, minV).color(red, green, blue, alpha).light(light).next(); + drawer.vertex(corners[1].x, corners[1].y, corners[1].z).texture(maxU, minV).color(red, green, blue, alpha).light(light).next(); + drawer.vertex(corners[2].x, corners[2].y, corners[2].z).texture(maxU, maxV).color(red, green, blue, alpha).light(light).next(); + drawer.vertex(corners[3].x, corners[3].y, corners[3].z).texture(minU, maxV).color(red, green, blue, alpha).light(light).next(); + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java deleted file mode 100644 index 21294ca3..00000000 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.minelittlepony.unicopia.client.particle; - -import org.joml.Quaternionf; -import org.joml.Vector3f; - -import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect; -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.*; - -@Deprecated -public class RunesParticle extends OrientedBillboardParticle { - - private static final Identifier[] TEXTURES = new Identifier[] { - Unicopia.id("textures/particles/runes_0.png"), - Unicopia.id("textures/particles/runes_1.png"), - Unicopia.id("textures/particles/runes_2.png"), - Unicopia.id("textures/particles/runes_3.png"), - Unicopia.id("textures/particles/runes_4.png"), - Unicopia.id("textures/particles/runes_5.png") - }; - - protected float targetSize = 3; - - protected float prevBaseSize = 0; - protected float baseSize = 0; - - private float prevRotationAngle; - private float rotationAngle; - - public RunesParticle(OrientedBillboardParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { - super(effect, world, x, y, z, velocityX, velocityY, velocityZ); - setMaxAge(70); - - red = world.random.nextFloat(); - green = world.random.nextFloat(); - blue = world.random.nextFloat(); - } - - @Override - public float getScale(float tickDelta) { - return MathHelper.lerp(tickDelta, prevBaseSize, baseSize) * super.getScale(tickDelta); - } - - @Override - protected Identifier getTexture() { - return TEXTURES[0]; - } - - private float getAlphaScale() { - float transitionScale = age < maxAge / 2 ? 5 : 3; - return (float)Math.min(1, Math.sin(Math.PI * age / maxAge) * transitionScale); - } - - @Override - protected int getBrightness(float tint) { - return 0xF000F0; - } - - @Override - protected void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta) { - - float alpha = this.alpha * getAlphaScale(); - - float angle = MathHelper.lerp(tickDelta, prevRotationAngle, rotationAngle); - - for (int i = 0; i < TEXTURES.length; i++) { - for (int dim = 0; dim < 3; dim++) { - RenderSystem.setShaderTexture(0, TEXTURES[i]); - RenderSystem.setShaderColor(red, green, blue, alpha / ((float)(dim * 3) + 1)); - - Vector3f[] corners = new Vector3f[]{ - new Vector3f(-1, -1, 0), - new Vector3f(-1, 1, 0), - new Vector3f( 1, 1, 0), - new Vector3f( 1, -1, 0) - }; - float scale = getScale(tickDelta); - - float ringSpeed = (i % 2 == 0 ? i : -1) * i; - - Quaternionf ringAngle = RotationAxis.POSITIVE_Z.rotationDegrees(angle * ringSpeed); - Quaternionf ringFlip = RotationAxis.POSITIVE_Y.rotationDegrees(angle * ringSpeed * dim); - Quaternionf ringRoll = RotationAxis.POSITIVE_X.rotationDegrees(angle * ringSpeed * dim); - - for(int k = 0; k < 4; ++k) { - Vector3f corner = corners[k]; - corner.rotate(ringAngle); - corner.rotate(ringFlip); - corner.rotate(ringRoll); - corner.rotate(rotation); - corner.mul(scale); - corner.add(x, y + 0.001F, z); - } - - renderQuad(te, buffer, corners, alpha, tickDelta); - } - } - - RenderSystem.setShaderColor(1, 1, 1, 1); - } - - @Override - public void tick() { - super.tick(); - - prevBaseSize = baseSize; - if (baseSize < targetSize) { - baseSize += 0.1F; - } - if (baseSize > targetSize) { - baseSize -= 0.1F; - } - - rotationAngle = (rotationAngle + 0.3F) % 360; - prevRotationAngle = rotationAngle - 0.3F; - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java index b815f246..994082f4 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.datagen.providers; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; - import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.advancement.CustomEventCriterion; @@ -54,31 +53,37 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { createTribeRootAdvancement(consumer, root, Race.PEGASUS).children(consumer, this::generatePegasusTribeAdvancementsTree); createTribeRootAdvancement(consumer, root, Race.UNICORN).children(consumer, this::generateUnicornTribeAdvancementsTree); - root.child(UItems.DRAGON_BREATH_SCROLL).criterion("has_scroll", hasItems(UItems.DRAGON_BREATH_SCROLL)).build(consumer, "take_a_note").children(p -> { - p.child(UItems.DRAGON_BREATH_SCROLL).criterion("send_scroll", dragonScroll(false, Items.WRITTEN_BOOK)).build(consumer, "dear_princess"); + root.child(UItems.DRAGON_BREATH_SCROLL).showToast().announce().criterion("has_scroll", hasItems(UItems.DRAGON_BREATH_SCROLL)).build(consumer, "take_a_note").children(p -> { + p.child(UItems.DRAGON_BREATH_SCROLL).criterion("send_book", dragonScroll(false, Items.WRITTEN_BOOK)).build(consumer, "dear_princess") + .child(UItems.DRAGON_BREATH_SCROLL).criterion("send_scroll", dragonScroll(false, UItems.DRAGON_BREATH_SCROLL)).build(consumer, "i_await_your_reply"); p.child(UItems.IMPORTED_OATS).hidden().frame(AdvancementFrame.CHALLENGE) .criterion("send_oats", dragonScroll(false, UItems.OATS, UItems.IMPORTED_OATS)) - .criterion("receieve_oats", dragonScroll(true, UItems.OATS, UItems.IMPORTED_OATS)) - .criteriaMerger(CriterionMerger.OR) - .build(consumer, "imported_oats"); + .criterion("receieve_oats", dragonScroll(true, UItems.IMPORTED_OATS)) + .criteriaMerger(CriterionMerger.OR).build(consumer, "imported_oats"); p.child(Items.CHIPPED_ANVIL).hidden().frame(AdvancementFrame.CHALLENGE).criterion("ding_sun", dingCelestia(Set.of(), Set.of(Race.BAT))).build(consumer, "blasphemy"); p.child(Items.CHIPPED_ANVIL).hidden().frame(AdvancementFrame.CHALLENGE).criterion("ding_sun", dingCelestia(Set.of(Race.BAT), Set.of())).build(consumer, "sweet_sweet_revenge"); }); - root.child(UItems.OATS).criterion("has_oats", hasItems(UItems.OATS)).build(consumer, "what_the_hay"); - root.child(UItems.IRON_HORSE_SHOE).criterion("killed_entity_with_horseshoe", killWithItems(UTags.FROM_HORSESHOES)).build(consumer, "dead_ringer"); - root.child(UItems.PINECONE).frame(AdvancementFrame.CHALLENGE).criterion("eat_pinecone", ConsumeItemCriterion.Conditions.item(UItems.PINECONE)).build(consumer, "eat_pinecone"); - root.child(UItems.GIANT_BALLOON).criterion("ride_balloon", CustomEventCriterion.create("ride_balloon")).build(consumer, "travelling_in_style"); - root.child(UItems.MUFFIN).hidden().criterion("has_muffin", hasItems(UItems.MUFFIN)).build(consumer, "baked_bads"); - root.child(UItems.HORSE_SHOE_FRIES).criterion("has_horse_shoe_fries", hasItems(UItems.HORSE_SHOE_FRIES)).build(consumer, "lucky"); - root.child(UItems.TOAST).criterion("has_toast", hasItems(UItems.TOAST)).build(consumer, "toast") + root.child(UItems.OATS).showToast().announce().criterion("has_oats", hasItems(UItems.OATS)).build(consumer, "oats_so_easy"); + root.child(Items.HAY_BLOCK).showToast().announce().criterion("eat_hay", ConsumeItemCriterion.Conditions.item(Items.HAY_BLOCK)).build(consumer, "what_the_hay"); + root.child(UItems.COPPER_HORSE_SHOE).showToast().announce().criterion("has_horseshoe", hasItems(UTags.HORSE_SHOES)).build(consumer, "blacksmith").children(p -> { + p.child(UItems.IRON_HORSE_SHOE).criterion("has_iron_horseshoe", hasItems(UItems.IRON_HORSE_SHOE)).build(consumer, "change_of_shoes") + .child(UItems.GOLDEN_HORSE_SHOE).criterion("has_gold_horseshoe", hasItems(UItems.GOLDEN_HORSE_SHOE)).build(consumer, "fashionably_expensive") + .child(UItems.NETHERITE_HORSE_SHOE).criterion("has_netherite_horseshoe", hasItems(UItems.NETHERITE_HORSE_SHOE)).build(consumer, "overkill"); + p.child(UItems.IRON_HORSE_SHOE).hidden().frame(AdvancementFrame.CHALLENGE).criterion("killed_entity_with_horseshoe", killWithItems(UTags.FROM_HORSESHOES)).build(consumer, "dead_ringer"); + }); + root.child(UItems.PINECONE).showToast().announce().frame(AdvancementFrame.CHALLENGE).criterion("eat_pinecone", ConsumeItemCriterion.Conditions.item(UItems.PINECONE)).build(consumer, "eat_pinecone"); + root.child(UItems.OAK_BASKET).showToast().criterion("has_basket", hasItems(UTags.BASKETS)).build(consumer, "basket_case") + .child(Items.LANTERN).showToast().criterion("construct_balloon", CustomEventCriterion.create("construct_balloon")).build(consumer, "aeronaut") + .child(UItems.GIANT_BALLOON).showToast().announce().frame(AdvancementFrame.CHALLENGE).criterion("ride_balloon", CustomEventCriterion.create("ride_balloon")).build(consumer, "travelling_in_style"); + root.child(UItems.MUFFIN).showToast().announce().hidden().criterion("has_muffin", hasItems(UItems.MUFFIN)).build(consumer, "baked_bads"); + root.child(UItems.HORSE_SHOE_FRIES).showToast().announce().criterion("has_horse_shoe_fries", hasItems(UItems.HORSE_SHOE_FRIES)).build(consumer, "lucky"); + root.child(UItems.TOAST).showToast().announce().criterion("has_toast", hasItems(UItems.TOAST)).build(consumer, "toast") .child(UItems.BURNED_TOAST).hidden().criterion("has_burned_toast", hasItems(UItems.BURNED_TOAST)).build(consumer, "burn_toast"); - root.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.FRESH_APPLES)).build(consumer, "apple_route").children(p -> { - p.child(UItems.SWEET_APPLE) - .criterion("has_all_apples", hasItems(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE)) - .build(consumer, "sweet_apple_acres"); + root.child(UItems.GREEN_APPLE).showToast().announce().criterion("has_apple", hasItems(UTags.FRESH_APPLES)).build(consumer, "apple_route").children(p -> { + p.child(UItems.SWEET_APPLE).criterion("has_all_apples", hasItems(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE)).build(consumer, "sweet_apple_acres"); p.child(UItems.ZAP_BULB).criterion("has_zap_apple", hasItems(UItems.ZAP_APPLE)).build(consumer, "trick_apple").children(pp -> { - pp.child(UItems.ZAP_APPLE).hidden().criterion("eat_trick_apple", CustomEventCriterion.createFlying("eat_trick_apple")).build(consumer, "eat_trick_apple"); - pp.child(UItems.ZAP_APPLE).hidden().criterion("feed_trick_apple", CustomEventCriterion.createFlying("feed_trick_apple")).build(consumer, "feed_trick_apple"); + pp.child(UItems.ZAP_APPLE).hidden().criterion("eat_trick_apple", CustomEventCriterion.createFlying("eat_trick_apple")).build(consumer, "eat_trick_apple"); + pp.child(UItems.ZAP_APPLE).hidden().criterion("feed_trick_apple", CustomEventCriterion.createFlying("feed_trick_apple")).build(consumer, "feed_trick_apple"); }); p.child(UItems.JUICE).criterion("has_juice", hasItems(UItems.JUICE)).build(consumer, "juice") .child(UItems.BURNED_JUICE).hidden().criterion("has_burned_juice", hasItems(UItems.BURNED_JUICE)).build(consumer, "burn_juice") @@ -149,13 +154,14 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { private void generateUnicornTribeAdvancementsTree(Consumer<Advancement> consumer, AdvancementDisplayBuilder.Parent parent) { parent.child(UItems.SPELLBOOK).criterion("has_spellbook", hasItems(UItems.SPELLBOOK)).build(consumer, "books").children(p -> { + //ItemPredicate bookPredicate = ItemPredicate.Builder.create().tag(ItemTags.BOOKSHELF_BOOKS).build(); + //p.child(Items.BOOK).hidden().frame(AdvancementFrame.CHALLENGE).criterion("has_books", InventoryChangedCriterion.Conditions.items(IntStream.range(0, 9 * 4).mapToObj(i -> bookPredicate).toArray(ItemPredicate[]::new))).build(consumer, "books_books_books"); p.child(UItems.CRYSTAL_SHARD).criterion("has_shard", hasItems(UItems.CRYSTAL_SHARD)).build(consumer, "crystaline").children(pp -> { - pp.child(UItems.CRYSTAL_HEART).criterion("power_up_heart", CustomEventCriterion.create("power_up_heart")).rewards(AdvancementRewards.Builder.experience(105)).build(consumer, "power_up_heart"); + pp.child(UItems.CRYSTAL_HEART).criterion("power_up_heart", CustomEventCriterion.create("power_up_heart")).rewards(AdvancementRewards.Builder.experience(105)).build(consumer, "power_up_heart"); }); - p.child(UItems.ALICORN_AMULET).criterion("has_alicorn_amulet", hasItems(UItems.ALICORN_AMULET)).build(consumer, "tempting") + p.child(UItems.ALICORN_AMULET).criterion("has_alicorn_amulet", hasItems(UItems.ALICORN_AMULET)).build(consumer, "tempted") .child(Items.CRYING_OBSIDIAN).criterion("light_altar", CustomEventCriterion.create("light_altar")).build(consumer, "hello_darkness_my_old_friend") - .child(UItems.BROKEN_ALICORN_AMULET).frame(AdvancementFrame.GOAL).criterion("defeat_sombra", CustomEventCriterion.create("defeat_sombra")).rewards(AdvancementRewards.Builder.experience(2000)).build(consumer, "save_the_day") - .children(pp -> { + .child(UItems.BROKEN_ALICORN_AMULET).frame(AdvancementFrame.GOAL).criterion("defeat_sombra", CustomEventCriterion.create("defeat_sombra")).rewards(AdvancementRewards.Builder.experience(2000)).build(consumer, "save_the_day").children(pp -> { pp.child(UItems.UNICORN_AMULET).frame(AdvancementFrame.GOAL).criterion("obtain_the_thing", hasItems(UItems.UNICORN_AMULET)).rewards(AdvancementRewards.Builder.experience(1100)).build(consumer, "ascension"); pp.child(UItems.BROKEN_ALICORN_AMULET).hidden().frame(AdvancementFrame.CHALLENGE).criterion("defeat_sombra_again", CustomEventCriterion.create("defeat_sombra", 2)).rewards(AdvancementRewards.Builder.experience(2000)).build(consumer, "doctor_sombrero"); }); @@ -169,15 +175,14 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { private void generateBatTribeAdvancementsTree(Consumer<Advancement> consumer, AdvancementDisplayBuilder.Parent parent) { parent.child(Items.LIGHT).criterion("look_into_sun", CustomEventCriterion.create("look_into_sun")).build(consumer, "praise_the_sun").children(p -> { p.child(UItems.SUNGLASSES).criterion("wear_shades", CustomEventCriterion.create("wear_shades")).build(consumer, "cool_potato"); - p.child(Items.BLACK_CANDLE).frame(AdvancementFrame.CHALLENGE).criterion("screech_twenty_mobs", CustomEventCriterion.createFlying("screech_twenty_mobs")).build(consumer, "screech_twenty_mobs").children(pp -> { - pp.child(Items.BRICK).frame(AdvancementFrame.CHALLENGE).criterion("super_scare_entity", CustomEventCriterion.createFlying("super_scare_entity")).build(consumer, "extra_spooky"); - }); + p.child(Items.BLACK_CANDLE).frame(AdvancementFrame.CHALLENGE).criterion("screech_twenty_mobs", CustomEventCriterion.createFlying("screech_twenty_mobs")).build(consumer, "screech_twenty_mobs") + .child(Items.BRICK).frame(AdvancementFrame.CHALLENGE).criterion("super_scare_entity", CustomEventCriterion.createFlying("super_scare_entity")).build(consumer, "extra_spooky"); p.child(Items.BLACK_CANDLE).frame(AdvancementFrame.CHALLENGE).criterion("screech_self", CustomEventCriterion.createFlying("screech_self")).build(consumer, "screech_self"); }); } private void generateEnchantmentsAdvancementsTree(Consumer<Advancement> consumer) { - AdvancementDisplayBuilder.create(Items.NETHERITE_SCRAP) + AdvancementDisplayBuilder.create(Items.NETHERITE_SCRAP).showToast().announce() .criterion("enchant_with_consumption", enchant(UEnchantments.CONSUMPTION)) .rewards(AdvancementRewards.Builder.experience(120)) .parent(new Identifier("story/enchant_item")) @@ -189,9 +194,10 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { .group("enchanting") .hidden() .build(consumer, "xp_miner"); - AdvancementDisplayBuilder.create(Items.GOLDEN_APPLE) + AdvancementDisplayBuilder.create(Items.GOLDEN_APPLE).showToast().announce() .criterion("enchant_with_heart_bound", enchant(UEnchantments.HEART_BOUND)) .rewards(AdvancementRewards.Builder.experience(120)) + .parent(new Identifier("story/enchant_item")) .group("enchanting") .build(consumer, "hearts_stronger_than_horses") .child(Items.GOLDEN_PICKAXE) @@ -215,7 +221,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { public static CriterionConditions dragonScroll(boolean receiving, ItemPredicate items) { return new SendViaDragonBreathScrollCriterion.Conditions( LootContextPredicate.EMPTY, - ItemPredicate.ANY, + items, receiving, Optional.empty(), TriState.DEFAULT, diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockStateModelGenerator.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockStateModelGenerator.java index 2b86e3d2..45274e75 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockStateModelGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockStateModelGenerator.java @@ -123,7 +123,7 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator { registerLog(UBlocks.STRIPPED_PALM_LOG).log(UBlocks.STRIPPED_PALM_LOG).wood(UBlocks.STRIPPED_PALM_WOOD); registerCubeAllModelTexturePool(UBlocks.PALM_PLANKS).family(UBlockFamilies.PALM); registerHangingSign(UBlocks.STRIPPED_PALM_LOG, UBlocks.PALM_HANGING_SIGN, UBlocks.PALM_WALL_HANGING_SIGN); - registerSimpleCubeAll(UBlocks.PALM_LEAVES); + registerSingleton(UBlocks.PALM_LEAVES, TexturedModel.LEAVES); // zap wood registerLog(UBlocks.ZAP_LOG) @@ -170,6 +170,7 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator { // shells registerAll(UBlockStateModelGenerator::registerShell, UBlocks.CLAM_SHELL, UBlocks.TURRET_SHELL, UBlocks.SCALLOP_SHELL); // other + registerSimpleCubeAll(UBlocks.WORM_BLOCK); registerBuiltinWithParticle(UBlocks.WEATHER_VANE, UBlocks.WEATHER_VANE.asItem()); registerWithStages(UBlocks.FROSTED_OBSIDIAN, Properties.AGE_3, BlockModels.CUBE_ALL, 0, 1, 2, 3); registerWithStagesBuiltinModels(UBlocks.ROCKS, Properties.AGE_7, 0, 1, 2, 3, 4, 5, 6, 7); @@ -381,9 +382,17 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator { Identifier middle = BlockModels.TEMPLATE_PILLAR.upload(pillar, textures, modelCollector); Identifier end = BlockModels.TEMPLATE_PILLAR_END.upload(pillar, textures, modelCollector); blockStateCollector.accept(MultipartBlockStateSupplier.create(pillar) - .with(BlockStateVariant.create().put(MODEL, middle)) - .with(When.create().set(Properties.NORTH, false), BlockStateVariant.create().put(MODEL, end).put(UVLOCK, true).put(X, R180)) - .with(When.create().set(Properties.SOUTH, false), BlockStateVariant.create().put(MODEL, end)) + .with(When.create().set(Properties.AXIS, Direction.Axis.X), BlockStateVariant.create().put(MODEL, middle).put(X, R90).put(Y, R90)) + .with(When.create().set(Properties.AXIS, Direction.Axis.X).set(Properties.NORTH, false), BlockStateVariant.create().put(MODEL, end).put(X, R270).put(Y, R90)) + .with(When.create().set(Properties.AXIS, Direction.Axis.X).set(Properties.SOUTH, false), BlockStateVariant.create().put(MODEL, end).put(X, R90).put(Y, R90)) + + .with(When.create().set(Properties.AXIS, Direction.Axis.Y), BlockStateVariant.create().put(MODEL, middle)) + .with(When.create().set(Properties.AXIS, Direction.Axis.Y).set(Properties.NORTH, false), BlockStateVariant.create().put(MODEL, end).put(X, R180)) + .with(When.create().set(Properties.AXIS, Direction.Axis.Y).set(Properties.SOUTH, false), BlockStateVariant.create().put(MODEL, end)) + + .with(When.create().set(Properties.AXIS, Direction.Axis.Z), BlockStateVariant.create().put(MODEL, middle).put(X, R90)) + .with(When.create().set(Properties.AXIS, Direction.Axis.Z).set(Properties.NORTH, false), BlockStateVariant.create().put(MODEL, end).put(X, R90)) + .with(When.create().set(Properties.AXIS, Direction.Axis.Z).set(Properties.SOUTH, false), BlockStateVariant.create().put(MODEL, end).put(X, R270)) ); ItemModels.TEMPLATE_PILLAR.upload(ModelIds.getItemModelId(pillar.asItem()), textures, modelCollector); } diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockTagProvider.java index 2deff29f..cc6d6411 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UBlockTagProvider.java @@ -48,6 +48,7 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider { getOrCreateTagBuilder(BlockTags.DRAGON_IMMUNE).add(UBlocks.FROSTED_OBSIDIAN, UBlocks.GOLDEN_OAK_LOG, UBlocks.GOLDEN_OAK_LEAVES); getOrCreateTagBuilder(BlockTags.FIRE).add(UBlocks.SPECTRAL_FIRE); getOrCreateTagBuilder(BlockTags.HOE_MINEABLE).add(UBlocks.HAY_BLOCK).addOptional(Unicopia.id("rice_block")).addOptional(Unicopia.id("straw_block")); + getOrCreateTagBuilder(BlockTags.SHOVEL_MINEABLE).add(UBlocks.WORM_BLOCK); addZapWoodset(); addPalmWoodset(); diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockLootTableProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockLootTableProvider.java index 9b3b4364..fba77f65 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockLootTableProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockLootTableProvider.java @@ -54,7 +54,8 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider { UBlocks.WEATHER_VANE, UBlocks.ZAP_FENCE_GATE, UBlocks.ZAP_FENCE, - UBlocks.ZAP_LOG, UBlocks.ZAP_PLANKS, UBlocks.ZAP_STAIRS, UBlocks.ZAP_WOOD + UBlocks.ZAP_LOG, UBlocks.ZAP_PLANKS, UBlocks.ZAP_STAIRS, UBlocks.ZAP_WOOD, + UBlocks.WORM_BLOCK ).forEach(this::addDrop); // slabs diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/URecipeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/URecipeProvider.java index 942131c8..ed82fb66 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/URecipeProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/URecipeProvider.java @@ -449,6 +449,9 @@ public class URecipeProvider extends FabricRecipeProvider { .pattern("---") .offerTo(exporter); + // worms + offerReversibleCompactingRecipes(exporter, RecipeCategory.BUILDING_BLOCKS, UItems.WHEAT_WORMS, RecipeCategory.BUILDING_BLOCKS, UBlocks.WORM_BLOCK); + // utility ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, Items.DIRT) .input('*', UItems.WHEAT_WORMS).criterion("has_wheat_worms", conditionsFromItem(UItems.WHEAT_WORMS)) @@ -457,6 +460,8 @@ public class URecipeProvider extends FabricRecipeProvider { .pattern("#*") .offerTo(exporter, convertBetween(Items.DIRT, UItems.WHEAT_WORMS)); + offerShapelessRecipe(exporter, Items.BONE_MEAL, UTags.SHELLS, "bonemeal", 3); + offer2x2CompactingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, Items.COBBLESTONE, UItems.ROCK); offerReversibleCompactingRecipesWithReverseRecipeGroup(exporter, RecipeCategory.MISC, UItems.PEBBLES, RecipeCategory.BUILDING_BLOCKS, Blocks.GRAVEL, convertBetween(UItems.PEBBLES, Blocks.GRAVEL), "pebbles"); offerShapelessRecipe(exporter, UItems.PEBBLES, Blocks.SUSPICIOUS_GRAVEL, "pebbles", 9); diff --git a/src/main/java/com/minelittlepony/unicopia/diet/PonyDiets.java b/src/main/java/com/minelittlepony/unicopia/diet/PonyDiets.java index 8e4558a9..3566bf06 100644 --- a/src/main/java/com/minelittlepony/unicopia/diet/PonyDiets.java +++ b/src/main/java/com/minelittlepony/unicopia/diet/PonyDiets.java @@ -77,21 +77,15 @@ public class PonyDiets implements DietView { @Override public void appendTooltip(ItemStack stack, @Nullable PlayerEntity user, List<Text> tooltip, TooltipContext context) { + if (initEdibility(stack, user)) { - Pony pony = Pony.of(user); + if (!((ItemDuck)stack.getItem()).getOriginalFoodComponent().isEmpty() || stack.getItem().getFoodComponent() != null) { + Pony pony = Pony.of(user); - tooltip.add(Text.translatable("unicopia.diet.information").formatted(Formatting.DARK_PURPLE)); - getEffects(stack, pony).appendTooltip(stack, tooltip, context); - - /*for (Race race : Race.REGISTRY) { - var diet = diets.get(race); - if (diet != null) { - tooltip.add(race.getDisplayName()); - diet.appendTooltip(stack, user, tooltip, context); - } - }*/ - - getDiet(pony).appendTooltip(stack, user, tooltip, context); + tooltip.add(Text.translatable("unicopia.diet.information").formatted(Formatting.DARK_PURPLE)); + getEffects(stack, pony).appendTooltip(stack, tooltip, context); + getDiet(pony).appendTooltip(stack, user, tooltip, context); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java index 1529989b..538e7e4a 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java @@ -8,7 +8,9 @@ import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.block.FenceGateBlock; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityPose; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MovementType; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.mob.MobEntity; import net.minecraft.nbt.NbtCompound; @@ -35,6 +37,14 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity @Override public void tick() { if (isGravityNegative()) { + if (isGravityNegative() && !entity.isSneaking() && entity.isInSneakingPose()) { + float currentHeight = entity.getDimensions(entity.getPose()).height; + float sneakingHeight = entity.getDimensions(EntityPose.STANDING).height; + + entity.move(MovementType.SELF, new Vec3d(0, -(currentHeight - sneakingHeight), 0)); + entity.setPose(EntityPose.STANDING); + } + if (entity.getY() > entity.getWorld().getHeight() + 64) { entity.damage(entity.getDamageSources().outOfWorld(), 4.0F); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/duck/RotatedView.java b/src/main/java/com/minelittlepony/unicopia/entity/duck/RotatedView.java index e5c60d40..0bc5855b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/duck/RotatedView.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/duck/RotatedView.java @@ -39,7 +39,8 @@ public interface RotatedView { if (!hasTransform() || rotations.isEmpty()) { return y; } - return y - ((y - rotations.peek()) * 2); + + return (rotations.peek() * 2) - y; } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/AirBalloonEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/AirBalloonEntity.java index d6f032c8..57cbc2ef 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/AirBalloonEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/AirBalloonEntity.java @@ -380,6 +380,9 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp getWorld().emitGameEvent(player, GameEvent.EQUIP, getBlockPos()); } setDesign(HotAirBalloonItem.getDesign(getWorld(), stack)); + if (hasBurner() && hasBalloon()) { + UCriteria.CONSTRUCT_BALLOON.trigger(player); + } return ActionResult.SUCCESS; } @@ -405,6 +408,9 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp if (!player.isSneaky()) { getWorld().emitGameEvent(player, GameEvent.EQUIP, getBlockPos()); } + if (hasBurner() && hasBalloon()) { + UCriteria.CONSTRUCT_BALLOON.trigger(player); + } return ActionResult.SUCCESS; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/ButterflyEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/ButterflyEntity.java index 088529b2..d1a43978 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/ButterflyEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/ButterflyEntity.java @@ -72,6 +72,10 @@ public class ButterflyEntity extends AmbientEntity { return createMobAttributes().add(EntityAttributes.GENERIC_MAX_HEALTH, 2); } + public static boolean canSpawn(EntityType<? extends ButterflyEntity> type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random) { + return world.getBlockState(pos.down()).isIn(BlockTags.ANIMALS_SPAWNABLE_ON); + } + @Override public float getSoundPitch() { return super.getSoundPitch() * 0.95F; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java new file mode 100644 index 00000000..91f9b407 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java @@ -0,0 +1,118 @@ +package com.minelittlepony.unicopia.entity.mob; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.particle.FootprintParticleEffect; +import com.minelittlepony.unicopia.particle.ParticleUtils; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.goal.ActiveTargetGoal; +import net.minecraft.entity.ai.goal.LookAroundGoal; +import net.minecraft.entity.ai.goal.LookAtEntityGoal; +import net.minecraft.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.entity.ai.goal.RevengeGoal; +import net.minecraft.entity.ai.goal.SwimGoal; +import net.minecraft.entity.ai.goal.WanderAroundFarGoal; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.particle.BlockStateParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.tag.BlockTags; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; + +public class SpecterEntity extends HostileEntity { + public static DefaultAttributeContainer.Builder createAttributes() { + return HostileEntity.createHostileAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 16F) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.5F); + } + + private double stepDistance; + private double nextStepDistance; + private boolean wasLeft; + + public SpecterEntity(EntityType<? extends HostileEntity> entityType, World world) { + super(entityType, world); + } + + @Override + protected void initGoals() { + this.goalSelector.add(1, new SwimGoal(this)); + this.goalSelector.add(4, new MeleeAttackGoal(this, 1.0, true)); + this.goalSelector.add(5, new WanderAroundFarGoal(this, 0.8)); + this.goalSelector.add(6, new LookAtEntityGoal(this, PlayerEntity.class, 8.0f)); + this.goalSelector.add(6, new LookAroundGoal(this)); + this.targetSelector.add(1, new RevengeGoal(this)); + this.targetSelector.add(2, new TargetGoal<>(this, PlayerEntity.class)); + } + + @SuppressWarnings("deprecation") + @Override + public void tick() { + Vec3d prevPosition = getPos(); + super.tick(); + if (getBrightnessAtEyes() < 0.5F || getTarget() != null) { + ParticleUtils.spawnParticles(ParticleTypes.AMBIENT_ENTITY_EFFECT, this, 6); + + if (getWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) { + if (getWorld().getBlockState(getBlockPos()).isIn(BlockTags.REPLACEABLE_BY_TREES)) { + getWorld().breakBlock(getBlockPos(), true); + } + } + } + + if (!hasVehicle() && isOnGround()) { + stepDistance += getPos().subtract(prevPosition).horizontalLength() * 0.6F; + if (stepDistance >= nextStepDistance) { + nextStepDistance = stepDistance + 1; + wasLeft = !wasLeft; + float offset = 0.4F; + float yaw = getHeadYaw(); + Vec3d offsetVec = new Vec3d((wasLeft ? offset : -offset), 0, 0).rotateY(yaw); + getWorld().addParticle(new FootprintParticleEffect(yaw), true, getX() + offsetVec.getX(), getY(), getZ() + offsetVec.getZ(), 0, 0, 0); + ParticleUtils.spawnParticles(new BlockStateParticleEffect(ParticleTypes.BLOCK, getSteppingBlockState()), getWorld(), getPos(), 6); + playSound(getSteppingBlockState().getSoundGroup().getStepSound(), 0.5F, 1); + } + } + } + + @Override + public float getSoundPitch() { + return super.getSoundPitch() * 0.3F; + } + + @Override + @Nullable + protected SoundEvent getHurtSound(DamageSource source) { + return null; + } + + @Override + protected void playSwimSound(float volume) { + + } + + @Override + protected void onSwimmingStart() { + + } + + static class TargetGoal<T extends LivingEntity> extends ActiveTargetGoal<T> { + public TargetGoal(SpecterEntity specter, Class<T> targetEntityClass) { + super(specter, targetEntityClass, true); + } + + @SuppressWarnings("deprecation") + @Override + public boolean canStart() { + return mob.getBrightnessAtEyes() < 0.5F && super.canStart(); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java index 924ca810..9200384f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/UEntities.java @@ -7,7 +7,6 @@ import com.minelittlepony.unicopia.entity.behaviour.EntityBehaviour; import com.minelittlepony.unicopia.projectile.MagicBeamEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.PhysicsBodyProjectileEntity; - import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext; import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; @@ -17,13 +16,17 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction.Location; import net.minecraft.entity.decoration.painting.PaintingVariant; import net.minecraft.entity.mob.FlyingEntity; +import net.minecraft.entity.mob.HostileEntity; import net.minecraft.registry.*; import net.minecraft.registry.tag.BiomeTags; +import net.minecraft.world.Heightmap.Type; public interface UEntities { - EntityType<ButterflyEntity> BUTTERFLY = register("butterfly", FabricEntityTypeBuilder.create(SpawnGroup.AMBIENT, ButterflyEntity::new) + EntityType<ButterflyEntity> BUTTERFLY = register("butterfly", FabricEntityTypeBuilder.createMob().spawnGroup(SpawnGroup.AMBIENT).entityFactory(ButterflyEntity::new) + .spawnRestriction(Location.NO_RESTRICTIONS, Type.WORLD_SURFACE_WG, ButterflyEntity::canSpawn) .dimensions(EntityDimensions.fixed(0.25F, 0.25F))); EntityType<MagicProjectileEntity> THROWN_ITEM = register("thrown_item", FabricEntityTypeBuilder.<MagicProjectileEntity>create(SpawnGroup.MISC, MagicProjectileEntity::new) .trackRangeBlocks(100) @@ -74,6 +77,11 @@ public interface UEntities { EntityType<IgnominiousBulbEntity> IGNOMINIOUS_BULB = register("ignominious_bulb", FabricEntityTypeBuilder.<IgnominiousBulbEntity>create(SpawnGroup.MISC, IgnominiousBulbEntity::new) .trackRangeChunks(8) .dimensions(EntityDimensions.fixed(3, 2))); + EntityType<SpecterEntity> SPECTER = register("specter", FabricEntityTypeBuilder.createMob().spawnGroup(SpawnGroup.MONSTER).entityFactory(SpecterEntity::new) + .spawnRestriction(Location.ON_GROUND, Type.WORLD_SURFACE, HostileEntity::canSpawnInDark) + .fireImmune() + .spawnableFarFromPlayer() + .dimensions(EntityDimensions.fixed(1, 2))); static <T extends Entity> EntityType<T> register(String name, FabricEntityTypeBuilder<T> builder) { EntityType<T> type = builder.build(); @@ -89,6 +97,7 @@ public interface UEntities { FabricDefaultAttributeRegistry.register(FRIENDLY_CREEPER, FriendlyCreeperEntity.createCreeperAttributes()); FabricDefaultAttributeRegistry.register(LOOT_BUG, LootBugEntity.createSilverfishAttributes()); FabricDefaultAttributeRegistry.register(IGNOMINIOUS_BULB, IgnominiousBulbEntity.createMobAttributes()); + FabricDefaultAttributeRegistry.register(SPECTER, SpecterEntity.createAttributes()); if (!Unicopia.getConfig().disableButterflySpawning.get()) { final Predicate<BiomeSelectionContext> butterflySpawnable = BiomeSelectors.foundInOverworld() @@ -105,6 +114,8 @@ public interface UEntities { ), SpawnGroup.AMBIENT, BUTTERFLY, 7, 5, 19); } + BiomeModifications.addSpawn(BiomeSelectors.spawnsOneOf(EntityType.ZOMBIE), SpawnGroup.MONSTER, SPECTER, 2, 1, 2); + UTradeOffers.bootstrap(); EntityBehaviour.bootstrap(); UEntityAttributes.bootstrap(); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCamera.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCamera.java index 26c6d4c7..61effece 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCamera.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCamera.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell; import com.minelittlepony.unicopia.client.render.spell.DarkVortexSpellRenderer; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.Vec3d; public class PlayerCamera extends MotionCompositor { @@ -18,30 +19,28 @@ public class PlayerCamera extends MotionCompositor { } public float calculateRoll() { + return player.getInterpolator().interpolate("roll", (float)applyModifiers(-getMotionRoll()), 15); + } - double roll = 0; + public float calculateFirstPersonRoll() { + return player.getInterpolator().interpolate("roll_fp", (float)applyModifiers(-getMotionRoll() * getFovScale() * 0.25F), 25); + } - if (player.getMotion().isFlying()) { - Vec3d vel = player.asEntity().getVelocity(); - - roll -= calculateRoll(player.asEntity(), vel.x, vel.y, vel.z); - } - - if (player.getPhysics().isGravityNegative()) { - roll *= -1; - roll += 180; - } - - if (player.asEntity().age > 10) { - roll = player.getInterpolator().interpolate("roll", (float)roll, 15); + private double getMotionRoll() { + if (!player.getMotion().isFlying() || player.asEntity().hasVehicle() || player.asEntity().isOnGround()) { + return 0; } + Vec3d vel = player.asEntity().getVelocity(); + return calculateRoll(player.asEntity(), vel.x, vel.y, vel.z); + } + private double applyModifiers(double motionRoll) { if (player.getAcrobatics().isFloppy()) { - roll += 90; + motionRoll += 90; } - return (float)roll; + return player.getPhysics().isGravityNegative() ? 180 - motionRoll : motionRoll; } public float calculatePitch(float pitch) { @@ -61,13 +60,16 @@ public class PlayerCamera extends MotionCompositor { } public double calculateFieldOfView(double fov) { - fov += player.getMagicalReserves().getExertion().get() / 5F; - fov += getEnergyAddition(); + fov += (player.getMagicalReserves().getExertion().get() / 5F) * getFovScale(); + fov += getEnergyAddition() * getFovScale(); fov += DarkVortexSpellRenderer.getCameraDistortion() * 2.5F; - return fov; } + private float getFovScale() { + return MinecraftClient.getInstance().options.getFovEffectScale().getValue().floatValue(); + } + protected float getEnergyAddition() { int maxE = (int)Math.floor(player.getMagicalReserves().getEnergy().get() * 100); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 35116ead..f6c82b63 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -32,7 +32,6 @@ import com.minelittlepony.unicopia.util.*; import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBlockTags; import net.minecraft.block.*; import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityType; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LightningEntity; @@ -253,18 +252,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab final MutableVector velocity = new MutableVector(entity.getVelocity()); - if (isGravityNegative()) { - velocity.y *= -1; - } - - if (isGravityNegative() && !entity.isSneaking() && entity.isInSneakingPose()) { - float currentHeight = entity.getDimensions(entity.getPose()).height; - float sneakingHeight = entity.getDimensions(EntityPose.STANDING).height; - - entity.setPos(entity.getX(), entity.getY() + currentHeight - sneakingHeight, entity.getZ()); - entity.setPose(EntityPose.STANDING); - } - FlightType type = recalculateFlightType(); boolean typeChanged = type != lastFlightType; @@ -396,10 +383,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab velocity.z /= heavyness; } - if (isGravityNegative()) { - velocity.y *= -1; - } - entity.setVelocity(velocity.toImmutable()); if (isFlying() && !entity.isFallFlying() && !pony.getAcrobatics().isHanging() && pony.isClient()) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index f71ef863..b1e811b0 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -5,9 +5,7 @@ import java.util.Optional; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -178,14 +176,6 @@ abstract class MixinLivingEntity extends Entity implements LivingEntityDuck, Equ } } - @ModifyConstant(method = "travel(Lnet/minecraft/util/math/Vec3d;)V", constant = { - @Constant(doubleValue = 0.08D), - @Constant(doubleValue = 0.01D) - }) - private double modifyGravity(double initial) { - return get().getPhysics().calcGravity(initial); - } - @Override public void updateItemUsage(Hand hand, ItemStack stack, int time) { activeItemStack = stack; diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java index d836f0fc..d9200a75 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java @@ -9,7 +9,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.entity.*; -import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; import net.minecraft.entity.EntityType; @@ -33,18 +32,6 @@ abstract class MixinMobEntity extends LivingEntity implements Equine.Container<C get().initAi(goalSelector, targetSelector); } - @Inject(method = "tickNewAi", at = @At("HEAD")) - public void beforeTickAi(CallbackInfo into) { - if (get().getPhysics().isGravityNegative()) { - ((RotatedView)getWorld()).pushRotation((int)getY()); - } - } - - @Inject(method = "tickNewAi", at = @At("RETURN")) - public void afterTickAi(CallbackInfo into) { - ((RotatedView)getWorld()).popRotation(); - } - @Inject(method = "prefersNewEquipment(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z", at = @At("HEAD"), cancellable = true) private void onPrefersNewEquipment(ItemStack newStack, ItemStack oldStack, CallbackInfoReturnable<Boolean> info) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerEntity.java index d61ad769..b67432fc 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinPlayerEntity.java @@ -97,14 +97,6 @@ abstract class MixinPlayerEntity extends LivingEntity implements Equine.Containe get().getMotion().getDimensions().calculateActiveEyeHeight(dimensions).ifPresent(info::setReturnValue); } - /* - @Inject(method = "getDimensions(Lnet/minecraft/entity/EntityPose;)Lnet/minecraft/entity/EntityDimensions;", - at = @At("RETURN"), - cancellable = true) - private void onGetDimensions(EntityPose pose, CallbackInfoReturnable<EntityDimensions> info) { - get().getMotion().getDimensions().calculateDimensions().ifPresent(info::setReturnValue); - }*/ - @Redirect(method = "getDimensions(Lnet/minecraft/entity/EntityPose;)Lnet/minecraft/entity/EntityDimensions;", at = @At( value = "INVOKE", diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java index 04db071b..99ca9150 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -1,19 +1,13 @@ package com.minelittlepony.unicopia.mixin; -import java.util.Stack; import java.util.function.Supplier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; -import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; @@ -22,20 +16,8 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source private final Supplier<BlockDestructionManager> destructions = BlockDestructionManager.create((World)(Object)this); - private int recurseCount = 0; - private final Stack<Integer> rotations = new Stack<>(); private boolean mirrorEntityStatuses; - @Override - public Stack<Integer> getRotations() { - return rotations; - } - - @Override - public boolean hasTransform() { - return recurseCount <= 0; - } - @Override public void setMirrorEntityStatuses(boolean enable) { mirrorEntityStatuses = enable; @@ -52,17 +34,5 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source entity.handleStatus(status); } } - - @ModifyVariable(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("HEAD")) - private BlockPos modifyBlockPos(BlockPos pos) { - pos = applyRotation(pos); - recurseCount = Math.max(0, recurseCount) + 1; - return pos; - } - - @Inject(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("RETURN")) - public void onSetBlockState(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, CallbackInfoReturnable<Boolean> info) { - recurseCount = Math.max(0, recurseCount - 1); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java index d71373fb..2fe4abe2 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java @@ -36,7 +36,7 @@ abstract class MixinGameRenderer implements AutoCloseable, SynchronousResourceRe @Inject(method = "renderWorld(FJLnet/minecraft/client/util/math/MatrixStack;)V", at = @At("HEAD")) private void beforeRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) { - UnicopiaClient.getCamera().ifPresent(c -> matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(c.calculateRoll()))); + UnicopiaClient.getCamera().ifPresent(c -> matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(c.calculateFirstPersonRoll()))); BatEyesApplicator.INSTANCE.enable(); } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java index 7bc83f17..55c8a70b 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java @@ -28,11 +28,11 @@ abstract class MixinKeyboardInput extends Input { movementSideways = -movementSideways; - if (player.asEntity().getAbilities().flying && !player.getPhysics().isFlying()) { + /*if (player.asEntity().getAbilities().flying && !player.getPhysics().isFlying()) { tmp = jumping; jumping = sneaking; sneaking = tmp; - } + }*/ } if (EffectUtils.getAmplifier(MinecraftClient.getInstance().player, UEffects.PARALYSIS) > 1) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBrain.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinBrain.java similarity index 87% rename from src/main/java/com/minelittlepony/unicopia/mixin/MixinBrain.java rename to src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinBrain.java index 7a7a7737..4e794c6a 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBrain.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinBrain.java @@ -1,4 +1,4 @@ -package com.minelittlepony.unicopia.mixin; +package com.minelittlepony.unicopia.mixin.gravity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -21,7 +21,7 @@ abstract class MixinBrain<E extends LivingEntity> { Equine<?> eq = Equine.of(entity).orElse(null); if (eq instanceof Living<?> && eq.getPhysics().isGravityNegative()) { - ((RotatedView)world).pushRotation((int)entity.getY()); + ((RotatedView)world).pushRotation((int)(entity.getY() + entity.getHeight() * 0.5F)); } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinClientWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinClientWorld.java new file mode 100644 index 00000000..98701eec --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinClientWorld.java @@ -0,0 +1,30 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.entity.Equine; +import com.minelittlepony.unicopia.entity.duck.RotatedView; + +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; + +@Mixin(ClientWorld.class) +abstract class MixinClientWorld implements RotatedView { + + @Inject(method = "tickEntity", at = @At("HEAD")) + private void beforeTickEntity(Entity entity, CallbackInfo info) { + if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + // pushRotation((int)(entity.getY() + entity.getHeight() * 0.5F)); + } + } + + @Inject(method = "tickEntity", at = @At("RETURN")) + private void afterTickEntity(Entity entity, CallbackInfo info) { + if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + // popRotation(); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java new file mode 100644 index 00000000..c0725d94 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java @@ -0,0 +1,76 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.entity.Equine; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.MovementType; +import net.minecraft.util.math.Vec3d; + +@Mixin(value = Entity.class, priority = 29000) +abstract class MixinEntity { + + // we invert y when moving + @ModifyVariable(method = "move", at = @At("HEAD"), argsOnly = true) + private Vec3d modifyMovement(Vec3d movement) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + return movement.multiply(1, -1, 1); + } + return movement; + } + + // fix on ground check + @Inject(method = "move", at = @At(value = "FIELD", target = "net/minecraft/entity/Entity.groundCollision:Z", shift = Shift.AFTER, ordinal = 0)) + private void onUpdateOnGroundFlag(MovementType movementType, Vec3d movement, CallbackInfo info) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + eq.get().asEntity().groundCollision = eq.get().asEntity().verticalCollision && movement.y > 0.0; + } + } + + // invert jumping velocity so we can jump + @Inject(method = "getJumpVelocityMultiplier", at = @At("RETURN"), cancellable = true) + private void onGetJumpVelocityMultiplier(CallbackInfoReturnable<Float> info) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + info.setReturnValue(-info.getReturnValue()); + } + } + + // invert offsets so it can properly find the block we're walking on + @ModifyVariable(method = "getPosWithYOffset", at = @At("HEAD"), argsOnly = true) + private float onGetPosWithYOffset(float offset) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + return -(eq.get().asEntity().getHeight() + offset); + } + return offset; + } + + // fix sprinting particles + @Inject(method = "spawnSprintingParticles", at = @At("HEAD"), cancellable = true) + protected void spawnSprintingParticles(CallbackInfo info) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + eq.get().getPhysics().spawnSprintingParticles(); + info.cancel(); + } + } + + // invert check for walking up a step + @ModifyVariable( + method = "adjustMovementForCollisions(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Vec3d;Lnet/minecraft/util/math/Box;Lnet/minecraft/world/World;Ljava/util/List;)Lnet/minecraft/util/math/Vec3d;", + at = @At("HEAD"), + argsOnly = true) + + private static Vec3d modifyMovementForStepheight(Vec3d movement, @Nullable Entity entity) { + if (entity != null && movement.getY() == entity.getStepHeight()) { + return movement.multiply(1, -1, 1); + } + return movement; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java new file mode 100644 index 00000000..2d9dfe6c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java @@ -0,0 +1,22 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import com.minelittlepony.unicopia.entity.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; + +@Mixin(LivingEntity.class) +abstract class MixinLivingEntity extends Entity implements Equine.Container<Living<?>> { + + private MixinLivingEntity() { super(null, null); } + + @ModifyConstant(method = "travel(Lnet/minecraft/util/math/Vec3d;)V", constant = { + @Constant(doubleValue = 0.08D), + @Constant(doubleValue = 0.01D) + }) + private double modifyGravity(double initial) { + return Math.abs(get().getPhysics().calcGravity(initial)); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinMobEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinMobEntity.java new file mode 100644 index 00000000..e72ec42a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinMobEntity.java @@ -0,0 +1,28 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.minelittlepony.unicopia.entity.*; +import com.minelittlepony.unicopia.entity.duck.RotatedView; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.MobEntity; + +@Mixin(MobEntity.class) +abstract class MixinMobEntity extends LivingEntity implements Equine.Container<Creature> { + private MixinMobEntity() { super(null, null); } + + @Inject(method = "tickNewAi", at = @At("HEAD")) + public void beforeTickAi(CallbackInfo into) { + if (get().getPhysics().isGravityNegative()) { + ((RotatedView)getWorld()).pushRotation((int)(getY() + getHeight() * 0.5F)); + } + } + + @Inject(method = "tickNewAi", at = @At("RETURN")) + public void afterTickAi(CallbackInfo into) { + ((RotatedView)getWorld()).popRotation(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerWorld.java new file mode 100644 index 00000000..d43d1570 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerWorld.java @@ -0,0 +1,29 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.entity.Equine; +import com.minelittlepony.unicopia.entity.duck.RotatedView; +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerWorld; + +@Mixin(ServerWorld.class) +abstract class MixinServerWorld implements RotatedView { + + @Inject(method = "tickEntity", at = @At("HEAD")) + private void beforeTickEntity(Entity entity, CallbackInfo info) { + if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + // pushRotation((int)(entity.getY() + entity.getHeight() * 0.5F)); + } + } + + @Inject(method = "tickEntity", at = @At("RETURN")) + private void afterTickEntity(Entity entity, CallbackInfo info) { + if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + // popRotation(); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinSoundSource.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinSoundSource.java new file mode 100644 index 00000000..7ffbad9f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinSoundSource.java @@ -0,0 +1,17 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import com.minelittlepony.unicopia.client.UnicopiaClient; +import net.minecraft.client.sound.Source; +import net.minecraft.util.math.Vec3d; + +@Mixin(Source.class) +abstract class MixinSoundSource { + @ModifyVariable(method = "setPosition", at = @At("HEAD"), argsOnly = true) + private Vec3d modifyPosition(Vec3d pos) { + return UnicopiaClient.getAdjustedSoundPosition(pos); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorld.java new file mode 100644 index 00000000..71428388 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorld.java @@ -0,0 +1,43 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import java.util.Stack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.entity.duck.RotatedView; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; + +@Mixin(World.class) +abstract class MixinWorld implements WorldAccess, RotatedView { + + private int recurseCount = 0; + private final Stack<Integer> rotations = new Stack<>(); + + @Override + public Stack<Integer> getRotations() { + return rotations; + } + + @Override + public boolean hasTransform() { + return recurseCount <= 0; + } + + @ModifyVariable(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("HEAD")) + private BlockPos modifyBlockPos(BlockPos pos) { + pos = applyRotation(pos); + recurseCount = Math.max(0, recurseCount) + 1; + return pos; + } + + @Inject(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("RETURN")) + public void onSetBlockState(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, CallbackInfoReturnable<Boolean> info) { + recurseCount = Math.max(0, recurseCount - 1); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorldChunk.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorldChunk.java similarity index 96% rename from src/main/java/com/minelittlepony/unicopia/mixin/MixinWorldChunk.java rename to src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorldChunk.java index 97f137d8..4a3c2ced 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorldChunk.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinWorldChunk.java @@ -1,4 +1,4 @@ -package com.minelittlepony.unicopia.mixin; +package com.minelittlepony.unicopia.mixin.gravity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/main/java/com/minelittlepony/unicopia/particle/FootprintParticleEffect.java b/src/main/java/com/minelittlepony/unicopia/particle/FootprintParticleEffect.java new file mode 100644 index 00000000..69ef2300 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/particle/FootprintParticleEffect.java @@ -0,0 +1,42 @@ +package com.minelittlepony.unicopia.particle; + +import java.util.Locale; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleType; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.Registries; + +public record FootprintParticleEffect ( + float yaw + ) implements ParticleEffect { + @SuppressWarnings("deprecation") + public static final ParticleEffect.Factory<FootprintParticleEffect> FACTORY = ParticleFactoryHelper.of(FootprintParticleEffect::new, FootprintParticleEffect::new); + + protected FootprintParticleEffect(ParticleType<FootprintParticleEffect> type, StringReader reader) throws CommandSyntaxException { + this(ParticleFactoryHelper.readFloat(reader)); + } + + protected FootprintParticleEffect(ParticleType<FootprintParticleEffect> particleType, PacketByteBuf buf) { + this(buf.readFloat()); + } + + @Override + public ParticleType<?> getType() { + return UParticles.FOOTPRINT; + } + + @Override + public void write(PacketByteBuf buf) { + buf.writeFloat(yaw); + } + + @Override + public String asString() { + return String.format(Locale.ROOT, "%s %.2f", Registries.PARTICLE_TYPE.getId(getType()), yaw); + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index 9bec2e5c..da302010 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -14,14 +14,12 @@ public interface UParticles { ParticleType<MagicParticleEffect> UNICORN_MAGIC = register("unicorn_magic", FabricParticleTypes.complex(MagicParticleEffect.FACTORY)); DefaultParticleType CHANGELING_MAGIC = register("changeling_magic", FabricParticleTypes.simple()); DefaultParticleType BUBBLE = register("bubble", FabricParticleTypes.simple()); + ParticleType<FootprintParticleEffect> FOOTPRINT = register("footprint", FabricParticleTypes.complex(FootprintParticleEffect.FACTORY)); ParticleType<BlockStateParticleEffect> DUST_CLOUD = register("dust_cloud", FabricParticleTypes.complex(BlockStateParticleEffect.PARAMETERS_FACTORY)); ParticleType<OrientedBillboardParticleEffect> RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY)); ParticleType<TargetBoundParticleEffect> RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.complex(TargetBoundParticleEffect.FACTORY)); - @Deprecated - ParticleType<OrientedBillboardParticleEffect> MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY)); - DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple()); ParticleType<SphereParticleEffect> SPHERE = register("sphere", FabricParticleTypes.complex(true, SphereParticleEffect.FACTORY)); diff --git a/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java b/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java index adff046a..0a14890d 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java +++ b/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.util; +import net.minecraft.util.Util; import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; @@ -14,7 +15,7 @@ public interface VoxelShapeUtil { Vec3d CENTER = new Vec3d(0.5, 0, 0.5); static Function<Direction, VoxelShape> rotator(VoxelShape base) { - return d -> rotate(base, d); + return Util.memoize(d -> rotate(base, d)); } static VoxelShape rotate(VoxelShape shape, Direction direction) { @@ -27,7 +28,7 @@ public interface VoxelShapeUtil { float angle = direction.asRotation() * MathHelper.RADIANS_PER_DEGREE; return VoxelShapes.union(VoxelShapes.empty(), shape.getBoundingBoxes().stream() .map(box -> { - //These first two are enough for orthogonal rotations + //These first two are enough for orthogonal rotations Vec3d a = rotate(box.minX, box.minZ, angle); Vec3d b = rotate(box.maxX, box.maxZ, angle); //These cover odd angles diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index ccba8c05..a83cc748 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -280,6 +280,7 @@ "block.unicopia.golden_oak_leaves": "Golden Oak Leaves", "block.unicopia.golden_oak_log": "Golden Oak Log", "block.unicopia.mango": "Mango", + "block.unicopia.worm_block": "Block of Worms", "block.unicopia.mango_leaves": "Mango Leaves", "block.unicopia.mango_sapling": "Mango Sapling", "block.unicopia.potted_mango_sapling": "Potted Mango Sapling", @@ -355,6 +356,7 @@ "entity.unicopia.butterfly": "Butterfly", "entity.unicopia.twittermite": "Twittermite", + "entity.unicopia.specter": "Specter", "entity.unicopia.cast_spell": "Cast Spell", "entity.unicopia.cast_spell.by": "a spell cast by %s", "entity.unicopia.spellbook": "Spellbook", @@ -1598,6 +1600,8 @@ "advancements.unicopia.take_a_note.description": "Obtain a dragon breath scroll", "advancements.unicopia.dear_princess.title": "Dear princess...", "advancements.unicopia.dear_princess.description": "Send a letter with a dragon's breath scroll", + "advancements.unicopia.i_await_your_reply.title": "I Await Your Reply", + "advancements.unicopia.i_await_your_reply.description": "Use the dragon's breath scroll to send someone a dragon's breath scroll", "advancements.unicopia.baked_bads.title": "Baked Bads", "advancements.unicopia.baked_bads.description": "Bake a delicious muffin", "advancements.unicopia.mid_flight_interruption.title": "Mid-Flight Interruption", @@ -1618,6 +1622,10 @@ "advancements.unicopia.eat_trick_apple.description": "Bite into a zap apple", "advancements.unicopia.eat_pinecone.title": "Desperation", "advancements.unicopia.eat_pinecone.description": "Eat a pinecone", + "advancements.unicopia.what_the_hay.title": "What The Hay", + "advancements.unicopia.what_the_hay.description": "Eat an entire block of hay", + "advancements.unicopia.oats_so_easy.title": "Oats So Easy", + "advancements.unicopia.oats_so_easy.description": "Farm some oats", "advancements.unicopia.imported_oats.title": "Delicious As They Are Expensive", "advancements.unicopia.imported_oats.description": "Send or receive fancy imported oats", @@ -1647,11 +1655,15 @@ "advancements.unicopia.sweet_apple_acres.description": "Obtain one of every apple", "advancements.unicopia.brew_cider.title": "Applejack's Finest", "advancements.unicopia.brew_cider.description": "Brew some cider", + "advancements.unicopia.basket_case.title": "Basket Case", + "advancements.unicopia.basket_case.description": "Weave a basket", + "advancements.unicopia.aeronaut.title": "Aeronaut", + "advancements.unicopia.aeronaut.description": "Equip your basket with a lantern and hot air balloon", "advancements.unicopia.travelling_in_style.title": "Travelling in Style", "advancements.unicopia.travelling_in_style.description": "Ride a hot air balloon", - "advancements.unicopia.night_route.title": "Children of The Night", - "advancements.unicopia.night_route.description": "Walk the path of the night", + "advancements.unicopia.bat_route.title": "Children of The Night", + "advancements.unicopia.bat_route.description": "Walk the path of the night", "advancements.unicopia.screech_twenty_mobs.title": "Terror From The Skies", "advancements.unicopia.screech_twenty_mobs.description": "Rain down terror on at least 20 mobs at once", "advancements.unicopia.screech_self.title": "Jeepers!", @@ -1668,6 +1680,14 @@ "advancements.unicopia.earth_route.description": "Join the Apple Clan", "advancements.unicopia.sticks_and_stones.title": "Sticks and Stones", "advancements.unicopia.sticks_and_stones.description": "Kill a mob by throwing rocks at it", + "advancements.unicopia.blacksmith.title": "Blacksmith", + "advancements.unicopia.blacksmith.description": "Craft a horseshoe", + "advancements.unicopia.change_of_shoes.title": "A Change of Shoes", + "advancements.unicopia.change_of_shoes.description": "Craft an iron horse shoe", + "advancements.unicopia.fashionably_expensive.title": "Fashionably Expensive", + "advancements.unicopia.fashionably_expensive.description": "Upgrade to a set of golden horse shoes", + "advancements.unicopia.overkill.title": "Overkill", + "advancements.unicopia.overkill.description": "Craft a netherite horse shoe", "advancements.unicopia.dead_ringer.title": "Dead Ringer", "advancements.unicopia.dead_ringer.description": "Kill a mob with a horseshoe", "advancements.unicopia.born_on_a_rock_farm.title": "Born on a Rock Farm", @@ -1675,8 +1695,8 @@ "advancements.unicopia.thats_unusual.title": "That's Unusual", "advancements.unicopia.thats_unusual.description": "But what does it do?", - "advancements.unicopia.sky_route.title": "Path of the Pegasus", - "advancements.unicopia.sky_route.description": "Join the Clousdale Pegasi", + "advancements.unicopia.pegasus_route.title": "Path of the Pegasus", + "advancements.unicopia.pegasus_route.description": "Join the Clousdale Pegasi", "advancements.unicopia.molting_season_1.title": "Molting Season", "advancements.unicopia.molting_season_1.description": "Drop your first feather whilst flying", "advancements.unicopia.molting_season_2.title": "Molting Season 2", @@ -1708,11 +1728,13 @@ "advancements.unicopia.deter_phantom.title": "What Flies Around", "advancements.unicopia.deter_phantom.description": "Get up there and give those phantoms a taste of their own medicine", - "advancements.unicopia.magical_route.title": "Horn of the Unicorn", - "advancements.unicopia.magical_route.description": "Delve into the world of glitter and rainbows", + "advancements.unicopia.unicorn_route.title": "Horn of the Unicorn", + "advancements.unicopia.unicorn_route.description": "Delve into the world of glitter and rainbows", "advancements.unicopia.books.title": "Books!", "advancements.unicopia.books.description": "This is MY spellbook and I'm going to READ it!", + "advancements.unicopia.books_books_books.title": "Books! Books! Books!", + "advancements.unicopia.books_books_books.description": "Have an inventory full of books", "advancements.unicopia.tempted.title": "Tempting...", "advancements.unicopia.tempted.description": "Put on the alicorn amulet", "advancements.unicopia.hello_darkness_my_old_friend.title": "Hello Darkness...", diff --git a/src/main/resources/assets/unicopia/particles/footprint.json b/src/main/resources/assets/unicopia/particles/footprint.json new file mode 100644 index 00000000..50c757f1 --- /dev/null +++ b/src/main/resources/assets/unicopia/particles/footprint.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "unicopia:footprint" + ] +} diff --git a/src/main/resources/assets/unicopia/textures/block/worm_block.png b/src/main/resources/assets/unicopia/textures/block/worm_block.png new file mode 100644 index 00000000..f27791b8 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/block/worm_block.png differ diff --git a/src/main/resources/assets/unicopia/textures/particle/footprint.png b/src/main/resources/assets/unicopia/textures/particle/footprint.png new file mode 100644 index 00000000..a0ea4822 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/particle/footprint.png differ diff --git a/src/main/resources/data/c/tags/items/raw_insects.json b/src/main/resources/data/c/tags/items/raw_insects.json index 4a791552..ad219e8b 100644 --- a/src/main/resources/data/c/tags/items/raw_insects.json +++ b/src/main/resources/data/c/tags/items/raw_insects.json @@ -2,7 +2,8 @@ "replace": false, "values": [ "minecraft:spider_eye", + "unicopia:butterfly", "unicopia:wheat_worms", - "unicopia:butterfly" + "unicopia:worm_block" ] } diff --git a/src/main/resources/data/unicopia/diets/food_effects/insect/raw.json b/src/main/resources/data/unicopia/diets/food_effects/insect/raw.json index 8683f240..01a176d0 100644 --- a/src/main/resources/data/unicopia/diets/food_effects/insect/raw.json +++ b/src/main/resources/data/unicopia/diets/food_effects/insect/raw.json @@ -1,8 +1,8 @@ { "tags": [ "unicopia:food_types/raw_insect" ], "food_component": { - "hunger": 1, - "saturation": 0.1 + "hunger": 6, + "saturation": 0.3 }, "ailment": { "effects": [ diff --git a/src/main/resources/data/unicopia/diets/races/changeling.json b/src/main/resources/data/unicopia/diets/races/changeling.json index a60fb6bd..c20c7753 100644 --- a/src/main/resources/data/unicopia/diets/races/changeling.json +++ b/src/main/resources/data/unicopia/diets/races/changeling.json @@ -74,6 +74,18 @@ ] } }, + { + "tags": [ + "unicopia:food_types/raw_insect" + ], + "food_component": { + "hunger": 3, + "saturation": 2 + }, + "ailment": { + "effects": [ ] + } + }, { "tags": [ "unicopia:food_types/cooked_fish", @@ -98,11 +110,14 @@ "tags": [ "unicopia:food_types/rotten_fish", "unicopia:food_types/cooked_insect", - "unicopia:food_types/raw_insect", "unicopia:food_types/cooked_meat", "unicopia:food_types/raw_meat", "unicopia:food_types/rotten_meat" ], + "food_component": { + "hunger": 6, + "saturation": 9 + }, "ailment": { "effects": [ { diff --git a/src/main/resources/data/unicopia/tags/items/groups/earth_pony.json b/src/main/resources/data/unicopia/tags/items/groups/earth_pony.json index 618a0532..d88b92b7 100644 --- a/src/main/resources/data/unicopia/tags/items/groups/earth_pony.json +++ b/src/main/resources/data/unicopia/tags/items/groups/earth_pony.json @@ -57,6 +57,7 @@ "unicopia:crispy_hay_fries", "unicopia:horse_shoe_fries", "unicopia:wheat_worms", + "unicopia:worm_block", "unicopia:muffin", "unicopia:acorn", "unicopia:pinecone", diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index d59bf63e..0d34a3bf 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -13,7 +13,6 @@ "MixinBlockEntityType", "MixinBlockItem", "MixinBoatEntity", - "MixinBrain", "MixinChunkBlockLightProvider", "MutableBlockLightStorage", "MixinDamageSource", @@ -53,8 +52,14 @@ "MixinVanillaBiomeParameters", "MixinWardenEntity", "MixinWorld", - "MixinWorldChunk", "PointOfInterestTypesAccessor", + "gravity.MixinBrain", + "gravity.MixinEntity", + "gravity.MixinLivingEntity", + "gravity.MixinMobEntity", + "gravity.MixinWorld", + "gravity.MixinServerWorld", + "gravity.MixinWorldChunk", "trinkets.MixinTrinketSurvivalSlot", "trinkets.MixinTrinketItem", "trinkets.MixinTrinketInventory", @@ -88,7 +93,9 @@ "client.MixinWorldRenderer", "client.sodium.MixinSodiumWorldRenderer", "client.minelp.MixinPonyPosture", - "trinkets.MixinTrinketCreativeSlot" + "trinkets.MixinTrinketCreativeSlot", + "gravity.MixinClientWorld", + "gravity.MixinSoundSource" ], "injectors": { "defaultRequire": 1