From b4a847e4b58407466c3306e2c73991a538999aa4 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 17:09:36 +0000 Subject: [PATCH 01/11] Update loom --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../unicopia/client/render/shader/ViewportShader.java | 3 +-- .../com/minelittlepony/unicopia/item/EnchantedStaffItem.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 51a392c2..285777fc 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } plugins { id 'java-library' - id 'fabric-loom' version '0.12-SNAPSHOT' + id 'fabric-loom' version '1.5-SNAPSHOT' id 'com.modrinth.minotaur' version '2.+' id 'org.ajoberstar.reckon' version '0.13.0' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102e..db9a6b82 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java index ebef6c6a..21df38bc 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java @@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.client.render.shader; import java.io.IOException; -import javax.annotation.Nullable; - +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import com.google.common.collect.*; diff --git a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java index b37d4cab..08798972 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; From 692db5a0707c3731aaddf1af5daa0996f3a6084c Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 17:11:39 +0000 Subject: [PATCH 02/11] Fix fall damage, ladders, hitbox calculations, clipping, camera offset, and unicorn's teleportation when in inverted gravity --- .../ability/UnicornTeleportAbility.java | 13 ++-- .../client/render/WorldRenderDelegate.java | 36 ++++----- .../unicopia/command/GravityCommand.java | 75 ++++++++++--------- .../unicopia/entity/EntityPhysics.java | 35 +-------- .../unicopia/entity/Living.java | 6 -- .../unicopia/entity/Physics.java | 2 - .../entity/player/PlayerDimensions.java | 6 +- .../unicopia/entity/player/PlayerPhysics.java | 4 - .../unicopia/entity/player/Pony.java | 5 +- .../unicopia/mixin/MixinLivingEntity.java | 22 ------ .../mixin/client/MixinKeyboardInput.java | 6 -- .../unicopia/mixin/gravity/MixinEntity.java | 72 ++++++++++++++---- .../mixin/gravity/MixinLivingEntity.java | 23 ++++++ .../MixinServerPlayNetworkHandler.java | 29 +++++++ .../gravity/MixinServerPlayerEntity.java | 24 ++++++ .../resources/assets/unicopia/lang/en_us.json | 1 + src/main/resources/unicopia.mixin.json | 2 + 17 files changed, 203 insertions(+), 158 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayNetworkHandler.java create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayerEntity.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java index 3401632f..7f75d688 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java @@ -27,6 +27,7 @@ import net.minecraft.sound.SoundCategory; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; @@ -89,8 +90,10 @@ public class UnicornTeleportAbility implements Ability<Pos> { return trace.getBlockOrEntityPos().map(pos -> { final BlockPos originalPos = pos; + Direction globalUp = player.getPhysics().isGravityNegative() ? Direction.DOWN : Direction.UP; + boolean originalPosHasSupport = exception(w, pos, player.asEntity()); - boolean originalPosValid = enterable(w, pos.up()) && enterable(w, pos.up(2)); + boolean originalPosValid = enterable(w, pos.offset(globalUp)) && enterable(w, pos.offset(globalUp, 2)); if (w.getBlockState(pos).isOf(Blocks.POWDER_SNOW) && !PowderSnowBlock.canWalkOnPowderSnow(player.asEntity())) { return null; @@ -111,11 +114,11 @@ public class UnicornTeleportAbility implements Ability<Pos> { if (pos.getX() != originalPos.getX() || pos.getZ() != originalPos.getZ()) { // check support int steps = 0; - while (enterable(w, pos.down())) { - pos = pos.down(); + while (enterable(w, pos.offset(globalUp.getOpposite()))) { + pos = pos.offset(globalUp.getOpposite()); if (++steps > 2) { if (originalPosValid) { - pos = originalPos.up(); + pos = originalPos.offset(globalUp); break; } else { return null; @@ -125,7 +128,7 @@ public class UnicornTeleportAbility implements Ability<Pos> { } if ((!enterable(w, pos) && exception(w, pos, player.asEntity())) - || (!enterable(w, pos.up()) && exception(w, pos.up(), player.asEntity()))) { + || (!enterable(w, pos.offset(globalUp)) && exception(w, pos.offset(globalUp), player.asEntity()))) { return null; } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java index ac9c3cdb..17594ba0 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java @@ -175,43 +175,39 @@ public class WorldRenderDelegate { boolean negative = pony.getPhysics().isGravityNegative(); - float roll = negative ? 180 : 0; - - roll = pony instanceof Pony ? ((Pony)pony).getInterpolator().interpolate("g_roll", roll, 15) : roll; - matrices.translate(x, y + owner.getHeight() / 2, z); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(roll)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(roll)); - if (pony instanceof Pony p) { - roll = p.getCamera().calculateRoll(); - if (negative) { - roll -= 180; - } + float sidewaysRoll = p.getCamera().calculateRoll(); if (p.getAcrobatics().isFloppy()) { matrices.translate(0, -0.5, 0); p.asEntity().setBodyYaw(0); p.asEntity().setYaw(0); - matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90)); + sidewaysRoll += 90; } - matrices.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw)); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(roll)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(90)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(sidewaysRoll)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90)); - float diveAngle = p.getInterpolator().interpolate("g_kdive", p.getMotion().isDiving() ? 80 : 0, 15); + float forwardPitch = p.getInterpolator().interpolate("g_kdive", p.getMotion().isDiving() ? 80 : 0, 15); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(diveAngle)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(forwardPitch)); if (p.getCompositeRace().includes(Race.SEAPONY) && pony.asEntity().isSubmergedInWater() && MineLPDelegate.getInstance().getPlayerPonyRace(p.asEntity()) != Race.SEAPONY) { ModelPartHooks.startCollecting(); } - } else if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) { - ModelPartHooks.startCollecting(); + } else { + float roll = negative ? 180 : 0; + + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(roll)); + + if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) { + ModelPartHooks.startCollecting(); + } } matrices.translate(-x, -y - owner.getHeight() / 2, -z); @@ -224,7 +220,7 @@ public class WorldRenderDelegate { } private void flipAngles(Entity entity) { - if (entity instanceof PlayerEntity) { + if (entity instanceof PlayerEntity player) { entity.prevYaw *= -1; entity.setYaw(entity.getYaw() * -1); diff --git a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java index c99aa75b..c5249dcb 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java @@ -1,15 +1,15 @@ package com.minelittlepony.unicopia.command; -import java.util.Arrays; -import java.util.stream.Stream; - -import com.google.common.collect.Streams; -import com.minelittlepony.unicopia.entity.player.Pony; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import com.minelittlepony.unicopia.entity.Living; import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.argument.EntityArgumentType; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; @@ -22,45 +22,48 @@ class GravityCommand { return CommandManager.literal("gravity").requires(s -> s.hasPermissionLevel(2)) .then(CommandManager.literal("get") .executes(context -> get(context.getSource(), context.getSource().getPlayer(), true)) - .then(CommandManager.argument("target", EntityArgumentType.player()) - .executes(context -> get(context.getSource(), EntityArgumentType.getPlayer(context, "target"), false)) + .then(CommandManager.argument("target", EntityArgumentType.entity()) + .executes(context -> get(context.getSource(), EntityArgumentType.getEntity(context, "target"), false)) )) .then(CommandManager.literal("set") .then(CommandManager.argument("gravity", FloatArgumentType.floatArg(-99, 99)) - .executes(context -> set(context.getSource(), context.getSource().getPlayer(), FloatArgumentType.getFloat(context, "gravity"), true)) - .then(CommandManager.argument("target", EntityArgumentType.player()) - .executes(context -> set(context.getSource(), EntityArgumentType.getPlayer(context, "target"), FloatArgumentType.getFloat(context, "gravity"), false)) + .executes(context -> set(context.getSource(), List.of(context.getSource().getPlayer()), FloatArgumentType.getFloat(context, "gravity"), true)) + .then(CommandManager.argument("target", EntityArgumentType.entities()) + .executes(context -> set(context.getSource(), EntityArgumentType.getEntities(context, "target"), FloatArgumentType.getFloat(context, "gravity"), false)) ))); } - static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) throws CommandSyntaxException { - sendFeedback(source, player, "get", false, Pony.of(player).getPhysics().getGravityModifier()); - return 0; - } + static int get(ServerCommandSource source, Entity target, boolean isSelf) throws CommandSyntaxException { + Living<?> l = Living.living(target); - static int set(ServerCommandSource source, PlayerEntity player, float gravity, boolean isSelf) { - - Pony iplayer = Pony.of(player); - - iplayer.getPhysics().setBaseGravityModifier(gravity); - iplayer.setDirty(); - - sendFeedback(source, player, "set", true, gravity); - return 0; - } - - - static void sendFeedback(ServerCommandSource source, PlayerEntity player, String key, boolean notifyTarget, Object...arguments) { - String translationKey = "commands.gravity." + key; - - if (source.getEntity() == player) { - source.sendFeedback(() -> Text.translatable(translationKey + ".self", arguments), true); + float gravity = l == null ? 1 : l.getPhysics().getGravityModifier(); + if (source.getEntity() == target) { + source.sendFeedback(() -> Text.translatable("commands.gravity.get.self", gravity), true); } else { - if (notifyTarget && source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { - player.sendMessage(Text.translatable(translationKey, arguments)); - } - - source.sendFeedback(() -> Text.translatable(translationKey + ".other", Streams.concat(Stream.of(player.getDisplayName()), Arrays.stream(arguments)).toArray()), true); + source.sendFeedback(() -> Text.translatable("commands.gravity.get.other", target.getDisplayName(), gravity), true); } + return 0; + } + + static int set(ServerCommandSource source, Collection<? extends Entity> targets, float gravity, boolean isSelf) { + List<Entity> affected = targets.stream().map(Living::living).filter(Objects::nonNull).map(l -> { + l.getPhysics().setBaseGravityModifier(gravity); + l.setDirty(); + if (l.asEntity() instanceof PlayerEntity player) { + if (source.getEntity() == player) { + player.sendMessage(Text.translatable("commands.gravity.set.self", gravity)); + } else if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { + player.sendMessage(Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity)); + } + } + return (Entity)l.asEntity(); + }).toList(); + + if (affected.size() == 1) { + source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", affected.get(0).getDisplayName()), true); + } else { + source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true); + } + return 0; } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java index 538e7e4a..749ee3cf 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java @@ -4,18 +4,13 @@ import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; import com.minelittlepony.unicopia.util.Copyable; import com.minelittlepony.unicopia.util.Tickable; -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; -import net.minecraft.particle.BlockStateParticleEffect; -import net.minecraft.particle.ParticleTypes; import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -37,22 +32,12 @@ 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); } - - entity.setOnGround(entity.verticalCollision && entity.getVelocity().getY() > 0); } - float gravity = this.getGravityModifier(); + float gravity = getGravityModifier(); if (gravity != lastGravity) { lastGravity = gravity; @@ -87,8 +72,6 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity @Override public BlockPos getHeadPosition() { - entity.setOnGround(false); - BlockPos pos = new BlockPos( MathHelper.floor(entity.getX()), MathHelper.floor(entity.getY() + entity.getHeight() + 0.20000000298023224D), @@ -99,29 +82,13 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity BlockPos below = pos.down(); BlockState block = entity.getWorld().getBlockState(below); if (block.isIn(BlockTags.FENCES) || block.isIn(BlockTags.WALLS) || block.getBlock() instanceof FenceGateBlock) { - entity.setOnGround(true); return below; } - } else { - entity.setOnGround(true); } return pos; } - @Override - public void spawnSprintingParticles() { - BlockState state = entity.getWorld().getBlockState(getHeadPosition()); - if (state.getRenderType() != BlockRenderType.INVISIBLE) { - Vec3d vel = entity.getVelocity(); - entity.getWorld().addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, state), - entity.getX() + (entity.getWorld().random.nextFloat() - 0.5D) * entity.getWidth(), - entity.getY() + entity.getHeight() - 0.1D, - entity.getZ() + (entity.getWorld().random.nextFloat() - 0.5D) * entity.getWidth(), - vel.x * -4, -1.5D, vel.z * -4); - } - } - @Override public void setBaseGravityModifier(float constant) { entity.getDataTracker().set(gravity, constant); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 947a33be..84dce958 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -476,12 +476,6 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste return false; } - public void onJump() { - if (getPhysics().isGravityNegative()) { - entity.setVelocity(entity.getVelocity().multiply(1, -1, 1)); - } - } - @Nullable public final Caster<?> getAttacker() { return attacker; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Physics.java b/src/main/java/com/minelittlepony/unicopia/entity/Physics.java index c7aff817..bbc2d1ce 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Physics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Physics.java @@ -21,8 +21,6 @@ public interface Physics extends NbtSerialisable { BlockPos getHeadPosition(); - void spawnSprintingParticles(); - default boolean isGravityNegative() { return getGravityModifier() < 0; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java index 70eee553..a2e5a329 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java @@ -25,11 +25,7 @@ public final class PlayerDimensions { .or(() -> physics.isFlyingSurvival ? FLYING_EYE_HEIGHT : physics.isGravityNegative() ? Optional.of(dimensions.height) : Optional.empty()) .map(h -> { if (physics.isGravityNegative()) { - if (pony.asEntity().isSneaking()) { - h += 0.2F; - } - - return dimensions.height - h; + return dimensions.height - h + 0.1F; } return h; }); 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 f6c82b63..8ac41371 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -301,10 +301,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab if (entity.isOnGround() || (!creative && entity.horizontalCollision)) { cancelFlight(false); } - - if (entity.isClimbing() && (entity.horizontalCollision || ((LivingEntityDuck)entity).isJumping())) { - velocity.y = -0.2F; - } } isFlyingSurvival = entity.getAbilities().flying && !creative; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 3cb7f3cf..0c78666f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -631,7 +631,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update float max = 0.6F; return Optional.of(new Vec3d( MathHelper.clamp(speed.x * factor, -max, max), - speed.y * ((speed.y * getPhysics().getGravitySignum()) > 0 ? 1.2 : 1.101), + speed.y * (speed.y > 0 ? 1.2 : 1.101), MathHelper.clamp(speed.z * factor, -max, max) )); } @@ -715,11 +715,8 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update } public Optional<Float> onImpact(float distance, float damageMultiplier, DamageSource cause) { - float originalDistance = distance; - distance *= gravity.getGravityModifier(); - boolean extraProtection = getSpellSlot().get(SpellType.SHIELD, false).isPresent(); if (!entity.isCreative() && !entity.isSpectator()) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index b1e811b0..7d41f099 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -128,11 +128,6 @@ abstract class MixinLivingEntity extends Entity implements LivingEntityDuck, Equ get().adjustMovementSpeedInWater(info.getReturnValue()).ifPresent(info::setReturnValue); } - @Inject(method = "jump()V", at = @At("RETURN")) - private void onJump(CallbackInfo info) { - get().onJump(); - } - @Inject(method = "tick()V", at = @At("HEAD"), cancellable = true) private void beforeTick(CallbackInfo info) { if (get().beforeUpdate()) { @@ -186,21 +181,4 @@ abstract class MixinLivingEntity extends Entity implements LivingEntityDuck, Equ setLivingFlag(2, hand == Hand.OFF_HAND); } } - - @Override - public BlockPos getBlockPos() { - if (get().getPhysics().isGravityNegative()) { - return get().getPhysics().getHeadPosition(); - } - return super.getBlockPos(); - } - - @Override - protected void spawnSprintingParticles() { - if (get().getPhysics().isGravityNegative()) { - get().getPhysics().spawnSprintingParticles(); - } else { - super.spawnSprintingParticles(); - } - } } 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 55c8a70b..6b4240d3 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinKeyboardInput.java @@ -27,12 +27,6 @@ abstract class MixinKeyboardInput extends Input { pressingRight = tmp; movementSideways = -movementSideways; - - /*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/gravity/MixinEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java index c0725d94..fe2eef70 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinEntity.java @@ -5,6 +5,7 @@ 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.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -12,7 +13,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.entity.Equine; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityPose; import net.minecraft.entity.MovementType; +import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; @Mixin(value = Entity.class, priority = 29000) @@ -21,7 +24,7 @@ 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()) { + if (unicopiaIsGravityInverted()) { return movement.multiply(1, -1, 1); } return movement; @@ -35,14 +38,6 @@ abstract class MixinEntity { } } - // 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) { @@ -53,12 +48,27 @@ abstract class MixinEntity { } // fix sprinting particles - @Inject(method = "spawnSprintingParticles", at = @At("HEAD"), cancellable = true) - protected void spawnSprintingParticles(CallbackInfo info) { + @ModifyArg(method = "spawnSprintingParticles", + at = @At(value = "INVOKE", + target = "net/minecraft/world/World.addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), + index = 2) + private double modifyParticleY(double y) { if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { - eq.get().getPhysics().spawnSprintingParticles(); - info.cancel(); + Entity self = eq.get().asEntity(); + return self.getHeight() - y + (self.getY() * 2); } + return y; + } + + // fix fall damage + @ModifyArg( + method = "move", + at = @At(value = "INVOKE", target = "net/minecraft/entity/Entity.fall(DZLnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)V")) + private double modifyFallDistance(double heightDifference) { + if (unicopiaIsGravityInverted()) { + return -heightDifference; + } + return heightDifference; } // invert check for walking up a step @@ -68,9 +78,43 @@ abstract class MixinEntity { argsOnly = true) private static Vec3d modifyMovementForStepheight(Vec3d movement, @Nullable Entity entity) { - if (entity != null && movement.getY() == entity.getStepHeight()) { + if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative() && movement.getY() == entity.getStepHeight()) { return movement.multiply(1, -1, 1); } return movement; } + + @Inject(method = {"calculateBoundsForPose"}, at = @At("RETURN"), cancellable = true) + private void adjustPoseBoxForGravity(EntityPose pos, CallbackInfoReturnable<Box> info) { + unicopiaReAnchorBoundingBox(info); + } + + @Inject(method = {"calculateBoundingBox"}, at = @At("RETURN"), cancellable = true) + private void adjustPoseBoxForGravity(CallbackInfoReturnable<Box> info) { + if (unicopiaReAnchorBoundingBox(info)) { + Entity self = (Entity)(Object)this; + self.setPos(self.getX(), info.getReturnValue().minY, self.getZ()); + } + } + + private boolean unicopiaReAnchorBoundingBox(CallbackInfoReturnable<Box> info) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + Entity self = eq.get().asEntity(); + Box box = info.getReturnValue(); + Box oldBox = self.getBoundingBox(); + double newHeight = box.getYLength(); + if (newHeight > oldBox.getYLength()) { + double targetMaxY = oldBox.maxY; + Vec3d min = new Vec3d(box.minX, targetMaxY - newHeight, box.minZ); + Vec3d max = new Vec3d(box.maxX, targetMaxY, box.maxZ); + info.setReturnValue(new Box(min, max)); + return true; + } + } + return false; + } + + private boolean unicopiaIsGravityInverted() { + return this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative(); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java index 2d9dfe6c..368eb0d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinLivingEntity.java @@ -1,11 +1,15 @@ package com.minelittlepony.unicopia.mixin.gravity; import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyConstant; import com.minelittlepony.unicopia.entity.*; + import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.util.math.BlockPos; @Mixin(LivingEntity.class) abstract class MixinLivingEntity extends Entity implements Equine.Container<Living<?>> { @@ -19,4 +23,23 @@ abstract class MixinLivingEntity extends Entity implements Equine.Container<Livi private double modifyGravity(double initial) { return Math.abs(get().getPhysics().calcGravity(initial)); } + + @ModifyArg(method = "fall", + at = @At(value = "INVOKE", + target = "net/minecraft/server/world/ServerWorld.spawnParticles(Lnet/minecraft/particle/ParticleEffect;DDDIDDDD)I"), + index = 2) + private double modifyParticleY(double y) { + if (get().getPhysics().isGravityNegative()) { + return y + getHeight(); + } + return y; + } + + @Override + public BlockPos getBlockPos() { + if (get().getPhysics().isGravityNegative()) { + return get().getPhysics().getHeadPosition(); + } + return super.getBlockPos(); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayNetworkHandler.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayNetworkHandler.java new file mode 100644 index 00000000..5c3b5452 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayNetworkHandler.java @@ -0,0 +1,29 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import com.minelittlepony.unicopia.entity.player.Pony; + +import net.minecraft.network.listener.ServerPlayPacketListener; +import net.minecraft.network.listener.TickablePacketListener; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.EntityTrackingListener; + +@Mixin(ServerPlayNetworkHandler.class) +abstract class MixinServerPlayNetworkHandler +implements EntityTrackingListener, +TickablePacketListener, +ServerPlayPacketListener { + @Shadow public ServerPlayerEntity player; + + @ModifyVariable(method = "onPlayerMove", at = @At("STORE"), ordinal = 0) + private boolean flipLandingFlag(boolean value) { + if (Pony.of(this.player).getPhysics().isGravityNegative()) { + return !value; + } + return value; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayerEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayerEntity.java new file mode 100644 index 00000000..77783d4b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinServerPlayerEntity.java @@ -0,0 +1,24 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import com.minelittlepony.unicopia.entity.Equine; + +import net.minecraft.server.network.ServerPlayerEntity; + +@Mixin(ServerPlayerEntity.class) +abstract class MixinServerPlayerEntity { + @ModifyVariable( + method = "handleFall(DDDZ)V", + at = @At("HEAD"), + ordinal = 1, + argsOnly = true) + private double modifyFallDistance(double value) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + return -value; + } + return value; + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index a83cc748..0941798f 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -1383,6 +1383,7 @@ "commands.gravity.set": "Your gravity has been updated to %f", "commands.gravity.set.self": "Set own gravity to %f", "commands.gravity.set.other": "Set %s's gravity to %f", + "commands.gravity.set.multiple": "Updated %s entities", "unicopia.options.title": "Unicopia Options", "unicopia.options.ignore_mine_lp": "Ignore Mine Little Pony", diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 0d34a3bf..4f3227b4 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -59,6 +59,8 @@ "gravity.MixinMobEntity", "gravity.MixinWorld", "gravity.MixinServerWorld", + "gravity.MixinServerPlayerEntity", + "gravity.MixinServerPlayNetworkHandler", "gravity.MixinWorldChunk", "trinkets.MixinTrinketSurvivalSlot", "trinkets.MixinTrinketItem", From 5cfebba12e9e67bc3d9b5f0b6d1a27ea174aadb9 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 19:05:57 +0000 Subject: [PATCH 03/11] Fix quilt crash --- src/main/java/com/minelittlepony/unicopia/block/UBlocks.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 32e48568..c5779abd 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -330,7 +330,7 @@ public interface UBlocks { FlammableBlockRegistry.getDefaultInstance().add(BANANAS, 5, 20); FlammableBlockRegistry.getDefaultInstance().add(CURING_JOKE, 60, 100); - CompostingChanceRegistry.INSTANCE.add(WORM_BLOCK, 8F); + CompostingChanceRegistry.INSTANCE.add(WORM_BLOCK, 1F); UBlockEntities.bootstrap(); EdibleBlock.bootstrap(); From 4a630dfcf911afeffeea1864102ebb6edccee9a7 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 20:21:12 +0000 Subject: [PATCH 04/11] Fix slime blocks in the upside down --- .../mixin/gravity/MixinPistonBlockEntity.java | 46 +++++++++++++++++++ src/main/resources/unicopia.mixin.json | 1 + 2 files changed, 47 insertions(+) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPistonBlockEntity.java diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPistonBlockEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPistonBlockEntity.java new file mode 100644 index 00000000..279047c7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPistonBlockEntity.java @@ -0,0 +1,46 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.entity.PistonBlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +@Mixin(PistonBlockEntity.class) +abstract class MixinPistonBlockEntity { + @Shadow + private static Box offsetHeadBox(BlockPos pos, Box box, PistonBlockEntity blockEntity) { + return box; + } + + @Shadow + private static boolean canMoveEntity(Box box, Entity entity, BlockPos pos) { + return false; + } + + @Shadow + private static void moveEntity(Direction direction, Entity entity, double distance, Direction movementDirection) { + + } + + @Inject(method = "moveEntitiesInHoneyBlock", at = @At("TAIL")) + private static void moveEntitiesInHoneyBlock(World world, BlockPos pos, float ticks, PistonBlockEntity tile, CallbackInfo info) { + Direction direction = tile.getMovementDirection(); + if (!direction.getAxis().isHorizontal()) { + return; + } + double blockY = tile.getPushedBlock().getCollisionShape(world, pos).getMin(Direction.Axis.Y); + Box box = offsetHeadBox(pos, new Box(0, blockY - 1.5000010000000001F, 0, 1, blockY, 1), tile); + double distance = ticks - tile.getProgress(1); + for (Entity entity2 : world.getOtherEntities(null, box, entity -> canMoveEntity(box, entity, pos))) { + moveEntity(direction, entity2, distance, direction); + } + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 4f3227b4..530d0226 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -58,6 +58,7 @@ "gravity.MixinLivingEntity", "gravity.MixinMobEntity", "gravity.MixinWorld", + "gravity.MixinPistonBlockEntity", "gravity.MixinServerWorld", "gravity.MixinServerPlayerEntity", "gravity.MixinServerPlayNetworkHandler", From dd8bf650d55d7a49c7e298bc41c2deac5c815b38 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 20:46:19 +0000 Subject: [PATCH 05/11] #168 Add speed boosts when performing stunts and add a stunt for flying at low altitude. --- .../entity/player/FlightStuntUtil.java | 19 +++++ .../unicopia/entity/player/PlayerPhysics.java | 73 ++++++++++++------- .../unicopia/util/MutableVector.java | 18 +++++ 3 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/player/FlightStuntUtil.java diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/FlightStuntUtil.java b/src/main/java/com/minelittlepony/unicopia/entity/player/FlightStuntUtil.java new file mode 100644 index 00000000..c5975dbe --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/FlightStuntUtil.java @@ -0,0 +1,19 @@ +package com.minelittlepony.unicopia.entity.player; + +import com.minelittlepony.unicopia.entity.mob.StormCloudEntity; +import com.minelittlepony.unicopia.util.MutableVector; + +import net.minecraft.util.math.BlockPos; + +public class FlightStuntUtil { + public static boolean isPerformingDive(Pony pony, MutableVector velocity) { + double horizontalSpeed = velocity.horizontalLengthSquared(); + double verticalSpeed = velocity.y; + return horizontalSpeed != 0 && verticalSpeed < -0.3F && (verticalSpeed / horizontalSpeed) < -0.3F; + } + + public static boolean isFlyingLow(Pony pony, MutableVector velocity) { + BlockPos pos = pony.asEntity().getBlockPos(); + return velocity.horizontalLengthSquared() > 0.005F && (pos.getY() - StormCloudEntity.findSurfaceBelow(pony.asWorld(), pos).getY()) < 6; + } +} 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 8ac41371..b4db56d0 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -60,6 +60,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab private int ticksInAir; private int ticksToGlide; private int ticksDiving; + private int ticksFlyingLow; private float thrustScale = 0; private float prevThrustScale; @@ -335,28 +336,9 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab velocity.y /= 2F; } - double horizontalSpeed = this.getHorizontalMotion(); - double verticalSpeed = velocity.y; - - if (Abilities.RAINBOOM.canUse(pony.getCompositeRace()) && horizontalSpeed != 0 && verticalSpeed < -0.3F && (verticalSpeed / horizontalSpeed) < -0.3F) { - ticksDiving++; - } else { - ticksDiving = 0; - } - - if (ticksDiving > 0 && ticksDiving % 25 == 0) { - pony.getMagicalReserves().getCharge().addPercent(12.5F); - } + tickStunts(velocity); } else { - prevStrafe = 0; - strafe = 0; - ticksInAir = 0; - wallHitCooldown = MAX_WALL_HIT_CALLDOWN; - soundPlaying = false; - descentRate = 0; - ticksDiving = 0; - updraft.update(0, 100); - windStrength.update(0, 100); + tickGrounded(); if (Abilities.RAINBOOM.canUse(pony.getCompositeRace()) && entity.isOnGround()) { pony.getMagicalReserves().getCharge().set(0); @@ -367,10 +349,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab } } } else { - descentRate = 0; - soundPlaying = false; - updraft.update(0, 100); - windStrength.update(0, 100); + tickGrounded(); } if (!entity.isOnGround()) { @@ -379,6 +358,10 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab velocity.z /= heavyness; } + float maximum = 1.5F; + velocity.x = MathHelper.clamp(velocity.x, -maximum, maximum); + velocity.y = MathHelper.clamp(velocity.y, -maximum, maximum); + velocity.z = MathHelper.clamp(velocity.z, -maximum, maximum); entity.setVelocity(velocity.toImmutable()); if (isFlying() && !entity.isFallFlying() && !pony.getAcrobatics().isHanging() && pony.isClient()) { @@ -397,6 +380,46 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab } } + private void tickGrounded() { + prevStrafe = 0; + strafe = 0; + ticksInAir = 0; + wallHitCooldown = MAX_WALL_HIT_CALLDOWN; + soundPlaying = false; + descentRate = 0; + ticksDiving = 0; + ticksFlyingLow = 0; + updraft.update(0, 0); + windStrength.update(0, 0); + } + + private void tickStunts(MutableVector velocity) { + boolean canPerformStunts = Abilities.RAINBOOM.canUse(pony.getCompositeRace()); + ticksDiving = canPerformStunts && FlightStuntUtil.isPerformingDive(pony, velocity) ? (ticksDiving + 1) : 0; + ticksFlyingLow = canPerformStunts && FlightStuntUtil.isFlyingLow(pony, velocity) ? (ticksFlyingLow + 1) : 0; + + if (ticksDiving > 0) { + float horDiveScale = MathHelper.clamp(ticksDiving / 100F, 0, 10); + float verDiveScale = MathHelper.clamp(ticksDiving / 90F, 0, 5); + velocity.multiply(1 + horDiveScale, 1 + verDiveScale, 1 + horDiveScale); + } + + if (ticksFlyingLow > 0) { + float horDiveScale = MathHelper.clamp(ticksFlyingLow / 1000F, 0, 0.9F); + float verDiveScale = MathHelper.clamp(ticksFlyingLow / 900F, 0, 0.5F); + velocity.multiply(1 + horDiveScale, 1 + verDiveScale, 1 + horDiveScale); + } + + if (pony.asEntity().age % 2 == 0) { + if (ticksDiving > 0) { + pony.getMagicalReserves().getCharge().addPercent(1F); + } + if (ticksFlyingLow > 0) { + pony.getMagicalReserves().getCharge().addPercent(ticksFlyingLow / 200F); + } + } + } + private void tickFlight(FlightType type, MutableVector velocity) { if (type.isArtifical()) { tickArtificialFlight(velocity); diff --git a/src/main/java/com/minelittlepony/unicopia/util/MutableVector.java b/src/main/java/com/minelittlepony/unicopia/util/MutableVector.java index c76e0209..8ea4aac6 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/MutableVector.java +++ b/src/main/java/com/minelittlepony/unicopia/util/MutableVector.java @@ -20,6 +20,12 @@ public class MutableVector { z = vec.z; } + public void multiply(double x, double y, double z) { + this.x *= x; + this.y *= y; + this.z *= z; + } + public void add(Vec3d vector) { add(vector.x, vector.y, vector.z); } @@ -38,6 +44,18 @@ public class MutableVector { this.z += z; } + public double horizontalLengthSquared() { + return x * x + z * z; + } + + public double verticalLengthSquared() { + return y * y; + } + + public double lengthSquared() { + return verticalLengthSquared() + horizontalLengthSquared(); + } + public Vec3d toImmutable() { return new Vec3d(x, y, z); } From 2ae28c72d3f222487407a12acaf65096382dba10 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Tue, 26 Mar 2024 22:00:43 +0000 Subject: [PATCH 06/11] Fix edge sneaking when upside down --- .../mixin/gravity/MixinPlayerEntity.java | 43 +++++++++++++++++++ src/main/resources/unicopia.mixin.json | 1 + 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPlayerEntity.java diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPlayerEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPlayerEntity.java new file mode 100644 index 00000000..e6b8b24b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/gravity/MixinPlayerEntity.java @@ -0,0 +1,43 @@ +package com.minelittlepony.unicopia.mixin.gravity; + +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.entity.Equine; + +import net.minecraft.entity.MovementType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Vec3d; + +@Mixin(PlayerEntity.class) +abstract class MixinPlayerEntity { + @ModifyVariable(method = "adjustMovementForSneaking", at = @At("HEAD"), argsOnly = true) + private Vec3d flipMovementForSneaking(Vec3d movement) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + return movement.multiply(1, -1, 1); + } + return movement; + } + + @Inject(method = "adjustMovementForSneaking", at = @At("RETURN"), cancellable = true) + private void unflipMovementForSneaking(Vec3d movement, MovementType type, CallbackInfoReturnable<Vec3d> info) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + info.setReturnValue(info.getReturnValue().multiply(1, -1, 1)); + } + } + + @ModifyArg(method = { "adjustMovementForSneaking", "method_30263" }, at = @At( + value = "INVOKE", + target = "net/minecraft/util/math/Box.offset(DDD)Lnet/minecraft/util/math/Box;"), + index = 1) + private double invertStepHeight(double stepHeight) { + if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) { + return -stepHeight; + } + return stepHeight; + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 530d0226..0a82eae8 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -58,6 +58,7 @@ "gravity.MixinLivingEntity", "gravity.MixinMobEntity", "gravity.MixinWorld", + "gravity.MixinPlayerEntity", "gravity.MixinPistonBlockEntity", "gravity.MixinServerWorld", "gravity.MixinServerPlayerEntity", From f84f45c47cf7624b6112be5993521907ecd2e640 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Wed, 27 Mar 2024 19:20:33 +0000 Subject: [PATCH 07/11] Run datagen before publish --- .github/workflows/gradle-publish.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index e93b8b24..ab6a77f9 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -17,6 +17,10 @@ jobs: uses: actions/setup-java@v1 with: java-version: 17 + - name: Prepare Datagen + uses: eskatos/gradle-command-action@v1 + with: + arguments: rundatagen - name: Publish Modrinth Jar env: MODRINTH_KEY: ${{ secrets.MODRINTH_KEY }} From e02c6f57a08d04e0095b8965b2efc3fa80b1fe3d Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Wed, 27 Mar 2024 19:22:11 +0000 Subject: [PATCH 08/11] Bump blockus --- BlockusAddon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BlockusAddon b/BlockusAddon index ec6ea81e..7170edad 160000 --- a/BlockusAddon +++ b/BlockusAddon @@ -1 +1 @@ -Subproject commit ec6ea81ed5f0862ab2dfa6201c66504287e3ef76 +Subproject commit 7170edad67426756e2383bd9464a8615e9bb4b3a From e931be3388b34154ac70d2a3fa49caca725cb85a Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Wed, 27 Mar 2024 19:23:16 +0000 Subject: [PATCH 09/11] You can now harvest pinecones and acorns from spruce and oak leaves using a hoe --- .../unicopia/InteractionManager.java | 6 ++ .../client/ClientInteractionManager.java | 7 ++ .../unicopia/item/ForageableItem.java | 93 +++++++++++++++++++ .../minelittlepony/unicopia/item/UItems.java | 5 +- 4 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 7c60d0d5..e0848e1a 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -14,6 +14,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.world.World; public class InteractionManager { @@ -90,4 +92,8 @@ public class InteractionManager { public void sendPlayerLookAngles(PlayerEntity player) { } + + public void addBlockBreakingParticles(BlockPos pos, Direction direction) { + + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java index 837b65fd..13352054 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java @@ -41,6 +41,8 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.sound.SoundCategory; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.random.Random; import net.minecraft.world.World; @@ -161,4 +163,9 @@ public class ClientInteractionManager extends InteractionManager { c.networkHandler.sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(player.getYaw(), player.getPitch(), player.isOnGround())); } } + + @Override + public void addBlockBreakingParticles(BlockPos pos, Direction direction) { + client.particleManager.addBlockBreakingParticles(pos, direction); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java b/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java new file mode 100644 index 00000000..bb129cf6 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java @@ -0,0 +1,93 @@ +package com.minelittlepony.unicopia.item; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.minelittlepony.unicopia.InteractionManager; +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; +import com.minelittlepony.unicopia.server.world.BlockDestructionManager; + +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.HoeItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ToolMaterials; +import net.minecraft.registry.tag.BlockTags; +import net.minecraft.registry.tag.ItemTags; +import net.minecraft.sound.SoundCategory; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.WorldEvents; + +public class ForageableItem extends Item { + private static final List<ForageableItem> REGISTRY = new ArrayList<>(); + static { + UseBlockCallback.EVENT.register((PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) -> { + if (player.shouldCancelInteraction()) { + return ActionResult.PASS; + } + + ItemStack stack = player.getStackInHand(hand); + if (!stack.isIn(ItemTags.HOES)) { + return ActionResult.PASS; + } + + BlockPos pos = hitResult.getBlockPos(); + BlockState state = world.getBlockState(pos); + + ActionResult result = ActionResult.PASS; + + if (state.isIn(BlockTags.LEAVES)) { + player.swingHand(hand); + world.playSound(player, pos, state.getSoundGroup().getHitSound(), SoundCategory.BLOCKS); + InteractionManager.instance().addBlockBreakingParticles(pos, hitResult.getSide()); + + int miningLevel = (stack.getItem() instanceof HoeItem hoe ? hoe.getMaterial().getMiningLevel() : 59); + + for (ForageableItem item : REGISTRY) { + if ((result = item.onTryForage(world, pos, state, stack, player, miningLevel)).isAccepted()) { + stack.damage(1, player, p -> p.sendToolBreakStatus(hand)); + return result; + } + } + } + + return result.isAccepted() ? ActionResult.SUCCESS : ActionResult.PASS; + }); + } + + private final Supplier<Block> targetBlock; + + public ForageableItem(Settings settings, Supplier<Block> targetBlock) { + super(settings); + this.targetBlock = targetBlock; + REGISTRY.add(this); + } + + public ActionResult onTryForage(World world, BlockPos pos, BlockState state, ItemStack stack, PlayerEntity player, int miningLevel) { + if (state.isOf(targetBlock.get())) { + int spawnChance = (int)((1F - MathHelper.clamp(miningLevel / (float)ToolMaterials.NETHERITE.getMiningLevel(), 0, 1)) * 32); + spawnChance -= EnchantmentUtil.getLuck(1, player); + + if (spawnChance <= 0 || world.random.nextInt(spawnChance) == 0) { + Block.dropStack(world, pos, new ItemStack(this, 1 + EnchantmentHelper.getLooting(player))); + world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state)); + if (BlockDestructionManager.of(world).damageBlock(pos, world.getRandom().nextBetween(3, 7)) >= BlockDestructionManager.MAX_DAMAGE) { + world.breakBlock(pos, true); + } + return ActionResult.SUCCESS; + } + return ActionResult.FAIL; + } + return ActionResult.PASS; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index b75f9a6f..0c8fdaab 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -16,6 +16,7 @@ import com.terraformersmc.terraform.boat.api.TerraformBoatType; import com.terraformersmc.terraform.boat.api.TerraformBoatTypeRegistry; import com.terraformersmc.terraform.boat.api.item.TerraformBoatItemHelper; +import net.minecraft.block.Blocks; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.vehicle.BoatEntity; @@ -85,8 +86,8 @@ public interface UItems { Item WHEAT_WORMS = register("wheat_worms", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.WORMS)), ItemGroups.NATURAL); Item MUFFIN = register("muffin", new MuffinItem(new Item.Settings().maxCount(32).food(FoodComponents.BREAD), 0), ItemGroups.FOOD_AND_DRINK); - Item PINECONE = register("pinecone", new Item(new Item.Settings().food(UFoodComponents.PINECONE).maxCount(3)), ItemGroups.FOOD_AND_DRINK); - Item ACORN = register("acorn", new Item(new Item.Settings().food(UFoodComponents.ACORN).maxCount(16)), ItemGroups.FOOD_AND_DRINK); + Item PINECONE = register("pinecone", new ForageableItem(new Item.Settings().food(UFoodComponents.PINECONE).maxCount(16), () -> Blocks.SPRUCE_LEAVES), ItemGroups.FOOD_AND_DRINK); + Item ACORN = register("acorn", new ForageableItem(new Item.Settings().food(UFoodComponents.ACORN).maxCount(16), () -> Blocks.OAK_LEAVES), ItemGroups.FOOD_AND_DRINK); Item MANGO = register("mango", new Item(new Item.Settings().food(UFoodComponents.MANGO)), ItemGroups.FOOD_AND_DRINK); Item BANANA = register("banana", new Item(new Item.Settings().food(UFoodComponents.BANANA)), ItemGroups.FOOD_AND_DRINK); Item CURING_JOKE = register("curing_joke", new CuringJokeItem(UBlocks.CURING_JOKE, new Item.Settings().food(UFoodComponents.POISON_JOKE)), ItemGroups.NATURAL); From c0a64a80f11ea961693711e82b590334a3125624 Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Wed, 27 Mar 2024 19:23:39 +0000 Subject: [PATCH 10/11] Fixed eating rock stew also consuming the bowl --- src/main/java/com/minelittlepony/unicopia/item/UItems.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index 0c8fdaab..1f036829 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -102,7 +102,7 @@ public interface UItems { Item TOM = register("tom", new BluntWeaponItem(new Item.Settings(), ImmutableMultimap.of( EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, new EntityAttributeModifier(BluntWeaponItem.KNOCKBACK_MODIFIER_ID, "Weapon modifier", 0.9, EntityAttributeModifier.Operation.ADDITION) )), ItemGroups.NATURAL); - Item ROCK_STEW = register("rock_stew", new Item(new Item.Settings().food(FoodComponents.MUSHROOM_STEW)), ItemGroups.FOOD_AND_DRINK); + Item ROCK_STEW = register("rock_stew", new StewItem(new Item.Settings().food(FoodComponents.MUSHROOM_STEW).recipeRemainder(Items.BOWL)), ItemGroups.FOOD_AND_DRINK); Item ROCK_CANDY = register("rock_candy", new Item(new Item.Settings().food(UFoodComponents.CANDY).maxCount(16)), ItemGroups.FOOD_AND_DRINK); Item SALT_CUBE = register("salt_cube", new Item(new Item.Settings().food(UFoodComponents.SALT_CUBE)), ItemGroups.FOOD_AND_DRINK); From 7cf32cce521699ed37c03c5cdf5636fc425fcfbd Mon Sep 17 00:00:00 2001 From: Sollace <sollacea@gmail.com> Date: Wed, 27 Mar 2024 19:24:06 +0000 Subject: [PATCH 11/11] Added bowl of nuts, oatmeal cookie, and pinecone cookie --- .../datagen/providers/UModelProvider.java | 6 ++--- .../UBlockAdditionsLootTableProvider.java | 22 +++++++++++++----- .../providers/recipe/URecipeProvider.java | 11 +++++++++ .../minelittlepony/unicopia/item/UItems.java | 4 ++++ .../resources/assets/unicopia/lang/en_us.json | 3 +++ .../unicopia/textures/item/bowl_of_nuts.png | Bin 0 -> 8620 bytes .../unicopia/textures/item/oatmeal_cookie.png | Bin 0 -> 9087 bytes .../textures/item/pinecone_cookie.png | Bin 0 -> 9118 bytes .../tags/items/food_types/baked_goods.json | 3 +++ .../tags/items/groups/earth_pony.json | 3 +++ 10 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/assets/unicopia/textures/item/bowl_of_nuts.png create mode 100644 src/main/resources/assets/unicopia/textures/item/oatmeal_cookie.png create mode 100644 src/main/resources/assets/unicopia/textures/item/pinecone_cookie.png diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UModelProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UModelProvider.java index 64bbc4be..1c58e4f7 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UModelProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UModelProvider.java @@ -57,7 +57,7 @@ public class UModelProvider extends FabricModelProvider { public void generateItemModels(ItemModelGenerator itemModelGenerator) { ItemModels.register(itemModelGenerator, UItems.ACORN, UItems.APPLE_PIE_HOOF, UItems.APPLE_PIE_SLICE, UItems.APPLE_PIE, - UItems.BANANA, UItems.BOTCHED_GEM, UItems.BROKEN_SUNGLASSES, UItems.BURNED_JUICE, UItems.BURNED_TOAST, + UItems.BANANA, UItems.BOTCHED_GEM, UItems.BOWL_OF_NUTS, UItems.BROKEN_SUNGLASSES, UItems.BURNED_JUICE, UItems.BURNED_TOAST, UItems.CARAPACE, UItems.CLAM_SHELL, UItems.COOKED_ZAP_APPLE, UItems.CLOUD_LUMP, UItems.CRISPY_HAY_FRIES, UItems.CRYSTAL_HEART, UItems.CRYSTAL_SHARD, UItems.DAFFODIL_DAISY_SANDWICH, UItems.DRAGON_BREATH_SCROLL, UItems.EMPTY_JAR, @@ -69,8 +69,8 @@ public class UModelProvider extends FabricModelProvider { UItems.JAM_TOAST, UItems.JUICE, UItems.LIGHTNING_JAR, UItems.MANGO, UItems.MUFFIN, - UItems.OATMEAL, - UItems.PEBBLES, UItems.PEGASUS_FEATHER, UItems.PINECONE, UItems.PINEAPPLE_CROWN, + UItems.OATMEAL, UItems.OATMEAL_COOKIE, + UItems.PEBBLES, UItems.PEGASUS_FEATHER, UItems.PINECONE, UItems.PINECONE_COOKIE, UItems.PINEAPPLE_CROWN, UItems.RAIN_CLOUD_JAR, UItems.ROCK_STEW, UItems.ROCK, UItems.ROTTEN_APPLE, UItems.SALT_CUBE, UItems.SCALLOP_SHELL, UItems.SHELLY, UItems.SOUR_APPLE_SEEDS, UItems.SOUR_APPLE, UItems.SPELLBOOK, UItems.STORM_CLOUD_JAR, UItems.SWEET_APPLE_SEEDS, UItems.SWEET_APPLE, diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockAdditionsLootTableProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockAdditionsLootTableProvider.java index 9788e234..4663bd66 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockAdditionsLootTableProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/loot/UBlockAdditionsLootTableProvider.java @@ -11,6 +11,7 @@ import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.data.server.loottable.BlockLootTableGenerator; import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.ItemConvertible; import net.minecraft.loot.LootPool; import net.minecraft.loot.LootTable; import net.minecraft.loot.condition.LootCondition; @@ -54,18 +55,29 @@ public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvid addVanillaDrop(Blocks.PODZOL, block -> wormDrops(block, 4, 0.06F, 0.062222223F, 0.065F, 0.077777776F, 0.2F)); addVanillaDrop(Blocks.DIAMOND_ORE, this::crystalShardDrops); addVanillaDrop(Blocks.DEEPSLATE_DIAMOND_ORE, this::crystalShardDrops); + addVanillaDrop(Blocks.OAK_LEAVES, block -> chanceDropWithShears(block, UItems.ACORN, GEMSTONES_FORTUNE_CHANCE)); + addVanillaDrop(Blocks.SPRUCE_LEAVES, block -> chanceDropWithShears(block, UItems.PINECONE, GEMSTONES_FORTUNE_CHANCE)); } private void addVanillaDrop(Block block, Function<Block, LootTable.Builder> lootTableFunction) { lootTables.put(new Identifier("unicopiamc", block.getLootTableId().getPath()), lootTableFunction.apply(block)); } + public LootTable.Builder chanceDropWithShears(Block block, ItemConvertible drop, float...chance) { + return LootTable.builder() + .pool(LootPool.builder() + .rolls(ConstantLootNumberProvider.create(1)) + .conditionally(WITHOUT_SILK_TOUCH.and(WITH_SHEARS)) + .with(chanceDrops(block, drop, 1, chance)) + ); + } + public LootTable.Builder wormDrops(Block block, int max, float...chance) { return LootTable.builder() .pool(LootPool.builder() .rolls(ConstantLootNumberProvider.create(1)) .conditionally(WITHOUT_SILK_TOUCH) - .with(wheatwormDrops(block, max, chance)) + .with(chanceDrops(block, UItems.WHEAT_WORMS, max, chance)) ); } @@ -75,7 +87,7 @@ public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvid .rolls(ConstantLootNumberProvider.create(1)) .conditionally(WITHOUT_SILK_TOUCH) .with(gemstoneDrops(block, 0.1F)) - .with(wheatwormDrops(block, max, chance)) + .with(chanceDrops(block, UItems.WHEAT_WORMS, max, chance)) ); } @@ -111,16 +123,14 @@ public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvid .conditionally(TableBonusLootCondition.builder(Enchantments.FORTUNE, GEMSTONES_FORTUNE_CHANCE)); } - public LootPoolEntry.Builder<?> wheatwormDrops(Block block, int max, float...chance) { - return applyExplosionDecay(block, ItemEntry.builder(UItems.WHEAT_WORMS) + public LootPoolEntry.Builder<?> chanceDrops(Block block, ItemConvertible drop, int max, float...chance) { + return applyExplosionDecay(block, ItemEntry.builder(drop) .apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(1, max))) ) .conditionally(TableBonusLootCondition.builder(Enchantments.FORTUNE, chance)); } - public static LootTable.Builder dropsWithGemfinding(Block drop, LootPoolEntry.Builder<?> child) { return BlockLootTableGenerator.drops(drop, WITHOUT_SILK_TOUCH_AND_GEM_FINDER, child); } - } 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 ed82fb66..57340e26 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 @@ -315,6 +315,17 @@ public class URecipeProvider extends FabricRecipeProvider { .input(UItems.ROCK, 3).criterion(hasItem(UItems.ROCK), conditionsFromItem(UItems.ROCK)) .input(Items.BOWL) .offerTo(exporter); + ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.BOWL_OF_NUTS) + .input(UItems.ACORN, 3).criterion(hasItem(UItems.ACORN), conditionsFromItem(UItems.ACORN)) + .input(Items.BOWL) + .offerTo(exporter); + ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.OATMEAL_COOKIE) + .input(UItems.OATS, 3).criterion(hasItem(UItems.OATS), conditionsFromItem(UItems.OATS)) + .offerTo(exporter); + ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.PINECONE_COOKIE) + .input(UItems.PINECONE).criterion(hasItem(UItems.PINECONE), conditionsFromItem(UItems.PINECONE)) + .input(Items.WHEAT, 2) + .offerTo(exporter); ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.ROCK_CANDY, 3) .input(Items.SUGAR, 6).criterion(hasItem(Items.SUGAR), conditionsFromItem(Items.SUGAR)) .input(UItems.PEBBLES, 3) diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index 1f036829..ce60d14b 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -75,6 +75,10 @@ public interface UItems { Item IMPORTED_OATS = register("imported_oats", new Item(new Item.Settings().food(UFoodComponents.IMPORTED_OATS)), ItemGroups.FOOD_AND_DRINK); Item OATMEAL = register("oatmeal", new OatmealItem(new Item.Settings().recipeRemainder(Items.BOWL).maxCount(1).food(UFoodComponents.OATMEAL)), ItemGroups.FOOD_AND_DRINK); + Item OATMEAL_COOKIE = register("oatmeal_cookie", new Item(new Item.Settings().food(FoodComponents.COOKIE)), ItemGroups.FOOD_AND_DRINK); + Item PINECONE_COOKIE = register("pinecone_cookie", new Item(new Item.Settings().food(FoodComponents.COOKIE)), ItemGroups.FOOD_AND_DRINK); + Item BOWL_OF_NUTS = register("bowl_of_nuts", new StewItem(new Item.Settings().food(FoodComponents.BAKED_POTATO).recipeRemainder(Items.BOWL)), ItemGroups.FOOD_AND_DRINK); + Item DAFFODIL_DAISY_SANDWICH = register("daffodil_daisy_sandwich", new Item(new Item.Settings().food(UFoodComponents.DAFODIL_DAISY_SANDWICH)), ItemGroups.FOOD_AND_DRINK); Item HAY_BURGER = register("hay_burger", new Item(new Item.Settings().maxCount(1).food(UFoodComponents.HAY_BURGER)), ItemGroups.FOOD_AND_DRINK); Item HAY_FRIES = register("hay_fries", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.HAY_FRIES)), ItemGroups.FOOD_AND_DRINK); diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 0941798f..8558c7b3 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -146,6 +146,9 @@ "item.unicopia.horse_shoe_fries": "Horse Shoe Fries", "item.unicopia.wheat_worms": "Wheat Worms", "item.unicopia.muffin": "Muffin", + "item.unicopia.oatmeal_cookie": "Oatmeal Cookie", + "item.unicopia.pinecone_cookie": "Pinecone Cookie", + "item.unicopia.bowl_of_nuts": "Bowl of Nuts", "item.unicopia.pegasus_amulet": "Wings of Icarus", "item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it", diff --git a/src/main/resources/assets/unicopia/textures/item/bowl_of_nuts.png b/src/main/resources/assets/unicopia/textures/item/bowl_of_nuts.png new file mode 100644 index 0000000000000000000000000000000000000000..8e684446c117429bfb1a6b04ce495bbffd916317 GIT binary patch literal 8620 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 Z1Z)@0k=!EON)o-*I*~Tm725d6{S$aW#=ign literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/item/oatmeal_cookie.png b/src/main/resources/assets/unicopia/textures/item/oatmeal_cookie.png new file mode 100644 index 0000000000000000000000000000000000000000..daa46c80f62cfae0c47d488bae33a9d8a0f1d036 GIT binary patch literal 9087 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 R271I`OI>eSw$?lT-vGR4fU^Jq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/item/pinecone_cookie.png b/src/main/resources/assets/unicopia/textures/item/pinecone_cookie.png new file mode 100644 index 0000000000000000000000000000000000000000..79fb1ed76ed999e863ea7a0f4878139271f7d9f6 GIT binary patch literal 9118 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 KbD?8!{NDhhiccW` literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/tags/items/food_types/baked_goods.json b/src/main/resources/data/unicopia/tags/items/food_types/baked_goods.json index 02828b2e..b28e7389 100644 --- a/src/main/resources/data/unicopia/tags/items/food_types/baked_goods.json +++ b/src/main/resources/data/unicopia/tags/items/food_types/baked_goods.json @@ -17,6 +17,9 @@ "unicopia:hay_fries", "unicopia:crispy_hay_fries", "unicopia:horse_shoe_fries", + "unicopia:oatmeal_cookie", + "unicopia:pinecone_cookie", + "unicopia:bowl_of_nuts", { "id": "farmersdelight:wheat_dough", "required": false }, { "id": "farmersdelight:raw_pasta", "required": false }, { "id": "farmersdelight:pie_crust", "required": false }, 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 d88b92b7..e3ec6fc3 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 @@ -51,6 +51,7 @@ "unicopia:oats", "unicopia:imported_oats", "unicopia:oatmeal", + "unicopia:oatmeal_cookie", "unicopia:daffodil_daisy_sandwich", "unicopia:hay_burger", "unicopia:hay_fries", @@ -61,6 +62,8 @@ "unicopia:muffin", "unicopia:acorn", "unicopia:pinecone", + "unicopia:pinecone_cookie", + "unicopia:bowl_of_nuts", "unicopia:crystal_shard", "unicopia:pebbles", "unicopia:rock",