From 5b3a8bee954ebcf60f33375c51babba10c0d4a1e Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 14:43:49 +0100 Subject: [PATCH 01/81] Limit AOE spell radius to 32 blocks. Fixes #450 --- .../unicopia/ability/magic/spell/AbstractAreaEffectSpell.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java index 1425a6ae..464b517a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java @@ -8,8 +8,10 @@ import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.effect.*; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import net.minecraft.util.math.MathHelper; + public abstract class AbstractAreaEffectSpell extends AbstractSpell { - protected static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); + protected static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> MathHelper.clamp(4 + power, 0, 32)); public static final TooltipFactory TOOLTIP = RANGE; protected AbstractAreaEffectSpell(CustomisedSpellType type) { From fab6e7b3dd5c607101854346998df5ae0167d2ce Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 14:52:00 +0100 Subject: [PATCH 02/81] You can no longer place spellbooks in occupied blocks. Fixes #451 --- .../unicopia/item/SpellbookItem.java | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java b/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java index 19a78a66..78bc3701 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java @@ -20,6 +20,8 @@ import net.minecraft.util.TypedActionResult; import net.minecraft.util.math.BlockPointer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Position; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class SpellbookItem extends BookItem implements Dispensable { @@ -29,15 +31,18 @@ public class SpellbookItem extends BookItem implements Dispensable { } @Override - public TypedActionResult dispenseStack(BlockPointer source, ItemStack stack) { - Direction facing = source.getBlockState().get(DispenserBlock.FACING); - BlockPos pos = source.getPos().offset(facing); + public TypedActionResult dispenseStack(BlockPointer pointer, ItemStack stack) { + Direction facing = pointer.getBlockState().get(DispenserBlock.FACING); + Position pos = DispenserBlock.getOutputLocation(pointer); float yaw = facing.getOpposite().asRotation(); - placeBook(stack, source.getWorld(), pos.getX(), pos.getY(), pos.getZ(), yaw, null); - stack.decrement(1); + if (placeBook(stack, pointer.getWorld(), pos, yaw, null)) { + stack.decrement(1); - return new TypedActionResult<>(ActionResult.SUCCESS, stack); + return new TypedActionResult<>(ActionResult.SUCCESS, stack); + } + + return new TypedActionResult<>(ActionResult.FAIL, stack); } @Override @@ -49,24 +54,28 @@ public class SpellbookItem extends BookItem implements Dispensable { if (!context.getWorld().isClient) { BlockPos pos = context.getBlockPos().offset(context.getSide()); - placeBook(context.getStack(), context.getWorld(), pos.getX(), pos.getY(), pos.getZ(), context.getPlayerYaw() + 180, player); + if (placeBook(context.getStack(), context.getWorld(), Vec3d.ofBottomCenter(pos), context.getPlayerYaw() + 180, player)) { + if (!player.getAbilities().creativeMode) { + player.getStackInHand(context.getHand()).decrement(1); + } - if (!player.getAbilities().creativeMode) { - player.getStackInHand(context.getHand()).decrement(1); + return ActionResult.SUCCESS; } - - return ActionResult.SUCCESS; } return ActionResult.PASS; } - private static void placeBook(ItemStack stack, World world, int x, int y, int z, float yaw, @Nullable Entity placer) { + private static boolean placeBook(ItemStack stack, World world, Position pos, float yaw, @Nullable Entity placer) { SpellbookEntity book = UEntities.SPELLBOOK.create(world); - book.refreshPositionAndAngles(x + 0.5, y, z + 0.5, 0, 0); + book.refreshPositionAndAngles(pos.getX(), pos.getY(), pos.getZ(), 0, 0); book.setHeadYaw(yaw); book.setYaw(yaw); + if (!book.canSpawn(world)) { + return false; + } + @Nullable NbtCompound tag = stack.getSubNbt("spellbookState"); if (tag != null) { @@ -80,6 +89,8 @@ public class SpellbookItem extends BookItem implements Dispensable { altar.generateDecorations(world); UCriteria.LIGHT_ALTAR.trigger(placer); }); + + return true; } } From b3068780aef9521c92d1dea39a045ce322746547 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 15:30:46 +0100 Subject: [PATCH 03/81] Fixed server flight state desync. Fixes #430, Fixes #421 (probably, cannot reproduce) --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c2789be6..d1339e66 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -242,7 +242,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab public void tick() { super.tick(); - if (pony.isClientPlayer() && isFlying() && (pony.getJumpingHeuristic().hasChanged(Heuristic.ONCE) || pony.sneakingChanged())) { + if (pony.isClientPlayer() && (pony.getJumpingHeuristic().hasChanged(Heuristic.ONCE) || pony.sneakingChanged())) { Channel.FLIGHT_CONTROLS_INPUT.sendToServer(new MsgPlayerFlightControlsInput(pony)); } @@ -369,7 +369,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab pony.getMagicalReserves().getCharge().set(0); } - if (!creative) { + if (!creative && !pony.isClient()) { checkAvianTakeoffConditions(velocity); } } From b53a51173c38e26437e3184d3dbcdbf870f2b662 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 16:59:41 +0100 Subject: [PATCH 04/81] Updated hud texture and added page indicators. Fixes #415 --- .../unicopia/client/gui/Slot.java | 13 +++---------- .../unicopia/client/gui/UHud.java | 18 ++++++++++++++---- .../assets/unicopia/textures/gui/hud.png | Bin 34102 -> 34038 bytes 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java b/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java index 80b7ef78..ced749de 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java @@ -14,6 +14,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.MutableText; +import net.minecraft.util.Colors; import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; @@ -145,10 +146,7 @@ class Slot { return; } - MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy().formatted(Formatting.BOLD); - - MatrixStack matrices = context.getMatrices(); - matrices.push(); + MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy(); int x = getX(); if (uHud.xDirection > 0) { @@ -158,9 +156,6 @@ class Slot { x -= uHud.client.textRenderer.getWidth(label)/2; } - matrices.translate(x, getY() + labelY, 0); - matrices.scale(0.5F, 0.5F, 0.5F); - ActivationType activation = KeyBindingsHandler.INSTANCE.getForcedActivationType(); if (activation.isResult()) { label = label.append("+T" + activation.getTapCount()); @@ -169,8 +164,6 @@ class Slot { } } - context.drawText(uHud.font, label, 0, 0, 0xFFFFFF, true); - - matrices.pop(); + DrawableUtil.drawScaledText(context, label, x, getY() + labelY, 0.5F, Colors.WHITE); } } \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index 1dd0ae28..590ed1e7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -51,8 +51,8 @@ public class UHud { private final List slots = List.of( new ManaRingSlot(this, AbilitySlot.PRIMARY, AbilitySlot.PASSIVE, 0, 0), - new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -8), - new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 40, 18) + new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -10), + new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 43, 10) ); @Nullable @@ -137,9 +137,11 @@ public class UHud { slots.forEach(slot -> slot.renderBackground(context, abilities, swap, tickDelta)); + int currentPage = Unicopia.getConfig().hudPage.get(); + int maxPages = pony.getAbilities().getMaxPage(); Ability ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY) - .getAbility(Unicopia.getConfig().hudPage.get()) + .getAbility(currentPage) .orElse(null); boolean canCast = ability == Abilities.CAST || ability == Abilities.KIRIN_CAST || ability == Abilities.SHOOT; @@ -168,6 +170,14 @@ public class UHud { slots.forEach(slot -> slot.renderLabel(context, abilities, tickDelta)); + //if (maxPages > 0) { + DrawableUtil.drawScaledText(context, Text.literal((currentPage + 1) + "/" + (maxPages + 1)), 44, 38, 0.5F, Colors.WHITE); + //down + context.drawTexture(HUD_TEXTURE, 42, 43, 52, currentPage == 0 ? 6 : 0, 6, 6, 128, 128); + //up + context.drawTexture(HUD_TEXTURE, 48, 43, 57, currentPage < maxPages ? 0 : 6, 8, 6, 128, 128); + //} + matrices.pop(); if (canCast) { @@ -188,7 +198,7 @@ public class UHud { int progress = Math.min(255, (int)(time * 255F / 20F)); if (progress > 8) { - int color = 0xFFFFFF; + int color = Colors.WHITE; int alpha = progress << 24 & -16777216; color |= alpha; diff --git a/src/main/resources/assets/unicopia/textures/gui/hud.png b/src/main/resources/assets/unicopia/textures/gui/hud.png index 7070f5ad3a7515d960cfd7d998a61611539e98ab..6fcab1f6c4636c2956df5e9d771c5e0ed64cf64f 100644 GIT binary patch literal 34038 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 literal 34102 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⪚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 Date: Mon, 16 Sep 2024 17:17:21 +0100 Subject: [PATCH 05/81] Fixed bat ponies unable to sleep at night when there is a thunderstorm. Fixes #436 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cfe236a9..4cc2b251 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -807,7 +807,7 @@ public class Pony extends Living implements Copyable, Update public ActionResult canSleepNow() { if (asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getSpecies().isNocturnal()) { - return asWorld().isDay() ? ActionResult.SUCCESS : ActionResult.FAIL; + return asWorld().isDay() || asWorld().getAmbientDarkness() >= 4 ? ActionResult.SUCCESS : ActionResult.FAIL; } return ActionResult.PASS; From 0ba3fd64a7b1bedd5ff48537d5b5f97aa0590e7f Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:51:41 +0100 Subject: [PATCH 06/81] Fixed earth ponies breaking blocks in adventure mode and protected regions. Fixes #434 --- .../unicopia/ability/EarthPonyGrowAbility.java | 5 ++++- .../unicopia/ability/EarthPonyKickAbility.java | 15 +++++++++++---- .../unicopia/ability/EarthPonyStompAbility.java | 15 ++++++++------- .../unicopia/entity/player/PlayerPhysics.java | 6 +++--- .../unicopia/entity/player/Pony.java | 2 +- .../server/world/BlockDestructionManager.java | 3 ++- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java index 744ee4a5..386fa26a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java @@ -14,6 +14,7 @@ import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.recipe.TransformCropsRecipe; import com.minelittlepony.unicopia.recipe.URecipes; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.TraceHelper; import com.minelittlepony.unicopia.util.VecHelper; @@ -70,7 +71,9 @@ public class EarthPonyGrowAbility implements Ability { for (BlockPos pos : BlockPos.iterate( data.pos().add(-2, -2, -2), data.pos().add( 2, 2, 2))) { - count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos); + if (player.canModifyAt(pos, ModificationType.PHYSICAL)) { + count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos); + } } } else { count = 1; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java index ca76579f..f8e4e861 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java @@ -17,6 +17,7 @@ import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.*; import net.minecraft.block.BeehiveBlock; @@ -98,7 +99,7 @@ public class EarthPonyKickAbility implements Ability { } BlockPos pos = kickLocation.pos(); - EarthPonyStompAbility.stompBlock(w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos)); + EarthPonyStompAbility.stompBlock(player, w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos)); player.setAnimation(Animation.KICK, Animation.Recipient.ANYONE); }); } @@ -165,10 +166,16 @@ public class EarthPonyKickAbility implements Ability { if (BlockDestructionManager.of(player.getWorld()).getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) { if (player.getWorld().random.nextInt(30) == 0) { - tree.logs().forEach(player.getWorld(), (w, state, p) -> w.breakBlock(p, true)); + tree.logs().forEach(player.getWorld(), (w, state, p) -> { + if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) { + w.breakBlock(p, true); + } + }); tree.leaves().forEach(player.getWorld(), (w, state, p) -> { - Block.dropStacks(w.getBlockState(p), w, p); - w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL); + if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) { + Block.dropStacks(w.getBlockState(p), w, p); + w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL); + } }); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index de4c8be8..e1761d25 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -19,6 +19,7 @@ import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.VecHelper; @@ -166,7 +167,7 @@ public class EarthPonyStompAbility implements Ability { double radius = rad + heavyness * 0.3; - spawnEffectAround(player, center, radius, rad); + spawnEffectAround(iplayer, player, center, radius, rad); ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); BlockState steppingState = player.getSteppingBlockState(); @@ -198,17 +199,17 @@ public class EarthPonyStompAbility implements Ability { return true; } - public static void spawnEffectAround(Entity source, BlockPos center, double radius, double range) { + public static void spawnEffectAround(Pony pony, Entity source, BlockPos center, double radius, double range) { BlockPos.stream(new BlockBox(center).expand(MathHelper.ceil(radius))).forEach(i -> { double dist = Math.sqrt(i.getSquaredDistance(source.getX(), source.getY(), source.getZ())); if (dist <= radius) { - spawnEffect(source.getWorld(), i, dist, range); + spawnEffect(pony, source.getWorld(), i, dist, range); } }); } - public static void spawnEffect(World w, BlockPos pos, double dist, double rad) { + public static void spawnEffect(Pony pony, World w, BlockPos pos, double dist, double rad) { if (w.getBlockState(pos.up()).isAir()) { BlockState state = w.getBlockState(pos); @@ -216,18 +217,18 @@ public class EarthPonyStompAbility implements Ability { float scaledHardness = (1 - hardness / 70); float damage = hardness < 0 ? 0 : MathHelper.clamp((int)((1 - dist / rad) * 9 * scaledHardness), 0, BlockDestructionManager.MAX_DAMAGE - 1); - stompBlock(w, pos, damage); + stompBlock(pony, w, pos, damage); } } - public static void stompBlock(World w, BlockPos pos, float damage) { + public static void stompBlock(Pony pony, World w, BlockPos pos, float damage) { BlockState state = w.getBlockState(pos); if (state.isAir() || damage <= 0) { return; } - if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) { + if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE && pony.canModifyAt(pos, ModificationType.PHYSICAL)) { w.breakBlock(pos, true); if (w instanceof ServerWorld) { 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 d1339e66..ca77955d 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -829,8 +829,8 @@ public class PlayerPhysics extends EntityPhysics implements Tickab .reduce(0, (u, pos) -> { if (pony.canModifyAt(pos, ModificationType.PHYSICAL)) { if (isEarthPonySmash) { - BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3)); - if (BlockDestructionManager.of(entity.getWorld()).getBlockDestruction(pos) >= 9) { + float destruction = BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3)); + if (destruction >= BlockDestructionManager.MAX_DAMAGE - 1 && pony.canModifyAt(pos, ModificationType.PHYSICAL)) { entity.getWorld().breakBlock(pos, true); } } else { @@ -862,7 +862,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (isFlying()) { playSound(USounds.ENTITY_PLAYER_PEGASUS_DASH, 1, 1); } else { - playSound(USounds.ENTITY_PLAYER_EARTHPONY_DASH, 2, 0.3F); + playSound(USounds.ENTITY_PLAYER_EARTHPONY_DASH, 2, 1.3F); } } 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 4cc2b251..9d09beaa 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -703,7 +703,7 @@ public class Pony extends Living implements Copyable, Update if (EffectUtils.hasExtraDefenses(entity)) { double radius = distance / 10; if (radius > 0) { - EarthPonyStompAbility.spawnEffectAround(entity, entity.getSteppingPos(), radius, radius); + EarthPonyStompAbility.spawnEffectAround(this, entity, entity.getSteppingPos(), radius, radius); } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java b/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java index 974abaef..25464839 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java @@ -17,6 +17,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class BlockDestructionManager implements Tickable { @@ -54,7 +55,7 @@ public class BlockDestructionManager implements Tickable { if (amount == 0) { return getBlockDestruction(pos); } - amount = Math.max(getBlockDestruction(pos), 0) + amount; + amount = MathHelper.clamp(Math.max(getBlockDestruction(pos), 0) + amount, 0, MAX_DAMAGE); setBlockDestruction(pos, amount); return amount; } From 6f9af460600553015c29d5a616ff10148e909ed0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:53:02 +0100 Subject: [PATCH 07/81] Fixed sounds not playing when dashing --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ca77955d..59eb9d80 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -530,7 +530,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab } private void playSound(SoundEvent sound, float volume, float pitch) { - entity.getWorld().playSoundFromEntity(entity, entity, sound, SoundCategory.PLAYERS, volume, pitch); + entity.getWorld().playSoundFromEntity(entity.getWorld().isClient ? entity : null, entity, sound, SoundCategory.PLAYERS, volume, pitch); } private void tickNaturalFlight(MutableVector velocity) { From 7c779eb2e39f2e7d03117390293ded8996345a0c Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:56:55 +0100 Subject: [PATCH 08/81] Fixed feathers dropping on the client. Fixes #383 --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 59eb9d80..6b729dfd 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -463,7 +463,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab entity.damage(entity.getDamageSources().generic(), 0.5F); } - if (type.isAvian()) { + if (type.isAvian() && !entity.getWorld().isClient) { if (pony.getObservedSpecies() != Race.BAT && entity.getWorld().random.nextInt(9000) == 0) { entity.dropItem(pony.getObservedSpecies() == Race.HIPPOGRIFF ? UItems.GRYPHON_FEATHER : UItems.PEGASUS_FEATHER); playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1); From d6286c7a00a5003e1fa53ad708beba7e58576755 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 18:12:58 +0100 Subject: [PATCH 09/81] Fixed player position messed up when mounting a boat whilst flying Players can now fly from boats again. Fixes #377 --- .../unicopia/ability/ToggleFlightAbility.java | 8 +++++++- .../unicopia/mixin/server/MixinServerPlayerEntity.java | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java index d1a45aa2..a3c3e6fa 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java @@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; public class ToggleFlightAbility implements Ability { @@ -27,7 +28,7 @@ public class ToggleFlightAbility implements Ability { @Nullable @Override public Optional prepare(Pony player) { - return Hit.of(!player.asEntity().hasVehicle() && !player.asEntity().isCreative() && !player.getPhysics().getFlightType().isGrounded()); + return Hit.of(!player.asEntity().isCreative() && !player.getPhysics().getFlightType().isGrounded()); } @Override @@ -59,6 +60,11 @@ public class ToggleFlightAbility implements Ability { player.subtractEnergyCost(1); if (!player.getPhysics().isFlying()) { + if (player.asEntity().hasVehicle()) { + Vec3d pos = player.asEntity().getPos(); + player.asEntity().stopRiding(); + player.asEntity().setPosition(pos.getX(), pos.getY() + 0.25, pos.getZ()); + } player.asEntity().addVelocity(0, player.getPhysics().getGravitySignum() * 0.7F, 0); Living.updateVelocity(player.asEntity()); player.getPhysics().startFlying(true); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java index 2ae21fe5..30a69af2 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java @@ -52,4 +52,9 @@ abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHan private void onUpdateKilledAdvancementCriterion(Entity entityKilled, int score, DamageSource damageSource, CallbackInfo info) { get().onKill(entityKilled, damageSource); } + + @Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("HEAD")) + private void onStartRiding(Entity entity, boolean force, CallbackInfoReturnable info) { + get().getPhysics().cancelFlight(true); + } } From 1c52237568518f25b31ca4bd6843f55a4d5d6fde Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:16:05 +0100 Subject: [PATCH 10/81] Fixed changling clinging and bat pony hanging abilities. Closes #404 --- .../unicopia/ability/BatPonyHangAbility.java | 2 +- .../unicopia/entity/EntityPhysics.java | 13 ++++++------ .../unicopia/entity/player/Acrobatics.java | 21 ++++++++++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java index 723cc0f5..95566b44 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java @@ -37,7 +37,7 @@ public class BatPonyHangAbility implements Ability { } return TraceHelper.findBlock(player.asEntity(), 5, 1) - .map(BlockPos::down) + .map(pos -> pos.down(player.getPhysics().getGravitySignum())) .filter(player.getAcrobatics()::canHangAt) .map(pos -> new Multi(pos, 1)); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java index c50d740f..bd51d7ba 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java @@ -10,12 +10,12 @@ import com.minelittlepony.unicopia.util.Tickable; 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.mob.MobEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; public class EntityPhysics implements Physics, Copyable>, Tickable { @@ -75,18 +75,17 @@ public class EntityPhysics implements Physics, Copyable 1.5) { @@ -156,8 +159,9 @@ public class Acrobatics implements Tickable, NbtSerialisable { } public void startHanging(BlockPos pos) { + boolean inverted = pony.getPhysics().isGravityNegative(); hangingPos.set(Optional.of(pos)); - entity.teleport(pos.getX() + 0.5, pos.getY() - 1, pos.getZ() + 0.5); + entity.teleport(pos.getX() + 0.5, pos.getY() - (inverted ? 0 : 1), pos.getZ() + 0.5); entity.setVelocity(Vec3d.ZERO); entity.setSneaking(false); entity.stopFallFlying(); @@ -165,14 +169,17 @@ public class Acrobatics implements Tickable, NbtSerialisable { } public boolean canHangAt(BlockPos pos) { - if (!pony.asWorld().isAir(pos) || !pony.asWorld().isAir(pos.down())) { + int gravity = pony.getPhysics().getGravitySignum() * (isHanging() && pony.getObservedSpecies() == Race.BAT ? -1 : 1); + BlockState state = pony.asWorld().getBlockState(pos); + + if (!pony.asWorld().isAir(pos) || !pony.asWorld().isAir(pos.down(gravity))) { return false; } - pos = pos.up(); - BlockState state = pony.asWorld().getBlockState(pos); + pos = pos.up(gravity); + state = pony.asWorld().getBlockState(pos); - return state.isSolidSurface(pony.asWorld(), pos, entity, Direction.DOWN) && entity.getWorld().isAir(entity.getBlockPos().down()); + return state.isSolidSurface(pony.asWorld(), pos, entity, gravity > 0 ? Direction.UP : Direction.DOWN); } private boolean canKeepHanging() { @@ -184,7 +191,7 @@ public class Acrobatics implements Tickable, NbtSerialisable { return true; } return getHangingPosition().filter(hangingPos -> { - return (race != Race.BAT || hangingPos.equals(pony.getOrigin().down())) && canHangAt(hangingPos); + return (race != Race.BAT || hangingPos.equals(pony.asEntity().getBlockPos().up(pony.getPhysics().isGravityNegative() ? 1 : 0))) && canHangAt(hangingPos); }).isPresent(); } From 6ac22e36a136c9e86a6dd7abb1039c6a99d1da2c Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:29:00 +0100 Subject: [PATCH 11/81] Fixed mobs getting stuck targetting an invalid entity. Fixes #414 --- .../com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java index 38328a96..a37eff54 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java @@ -49,6 +49,7 @@ public class BreakHeartGoal extends Goal { public void stop() { targetter.stop(); mob.getNavigation().stop(); + mob.setTarget(null); } @Override From 9d03ad75769ae53379cd3f08db5294e1b8b03270 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:58:41 +0100 Subject: [PATCH 12/81] Fix command outputs. Fixes #435 --- .../unicopia/command/ConfigCommand.java | 7 +-- .../unicopia/command/GravityCommand.java | 14 ++--- .../unicopia/command/ManaCommand.java | 5 +- .../unicopia/command/SpeciesCommand.java | 52 ++++++++++--------- .../unicopia/command/TraitCommand.java | 5 +- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java b/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java index 81b0abab..fb9b5ab2 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java @@ -23,7 +23,6 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -63,10 +62,8 @@ public class ConfigCommand { }))) ) .then(CommandManager.literal("list").executes(source -> ConfigCommand.>getProperty(configName, values -> { - ServerPlayerEntity player = source.getSource().getPlayerOrThrow(); - - player.sendMessage(Text.translatable("command.unicopia.config.list", configName, values.size()), false); - values.forEach(line -> player.sendMessage(Text.literal(line))); + source.getSource().sendFeedback(() -> Text.translatable("command.unicopia.config.list", configName, values.size()), false); + values.forEach(line -> source.getSource().sendFeedback(() -> Text.literal(line), false)); })) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java index a97272e9..d071b6bf 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java @@ -50,17 +50,19 @@ class GravityCommand { l.getPhysics().setBaseGravityModifier(gravity); 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)); + source.sendFeedback(() -> Text.translatable("commands.gravity.set.self", gravity), true); + } else { + if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { + player.sendMessage(Text.translatable("commands.gravity.set", gravity)); + } + + source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity), true); } } return (Entity)l.asEntity(); }).toList(); - if (affected.size() == 1) { - source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", affected.get(0).getDisplayName()), true); - } else { + if (affected.size() > 1) { source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true); } return 0; diff --git a/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java b/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java index 6383163a..18c6fd8b 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java @@ -23,7 +23,7 @@ public class ManaCommand { var pony = Pony.of(source.getSource().getPlayer()); var bar = type.getBar(pony.getMagicalReserves()); - source.getSource().getPlayer().sendMessage(Text.literal(type.name() + " is " + bar.get() + "/" + bar.getMax())); + source.getSource().sendFeedback(() -> Text.literal(type.name() + " is " + bar.get() + "/" + bar.getMax()), true); return 0; }) .then(CommandManager.argument("value", FloatArgumentType.floatArg()).executes(source -> { @@ -47,7 +47,8 @@ public class ManaCommand { pony.asWorld().playSound(null, pony.getOrigin(), USounds.Vanilla.ENTITY_PLAYER_LEVELUP, SoundCategory.PLAYERS, 1, 2); } bar.set(value); - source.getSource().getPlayer().sendMessage(Text.literal("Set " + type.name() + " to " + bar.get() + "/" + bar.getMax())); + var t = type; + source.getSource().sendFeedback(() -> Text.literal("Set " + t.name() + " to " + bar.get() + "/" + bar.getMax()), true); return 0; }))); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java b/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java index e1e9e999..5fecdbe6 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java @@ -44,10 +44,10 @@ class SpeciesCommand { )) .then(CommandManager.literal("describe") .then(CommandManager.argument("race", Race.argument()).suggests(UCommandSuggestion.ALL_RACE_SUGGESTIONS) - .executes(context -> describe(context.getSource().getPlayer(), Race.fromArgument(context, "race"))) + .executes(context -> describe(context.getSource(), Race.fromArgument(context, "race"))) )) .then(CommandManager.literal("list") - .executes(context -> list(context.getSource().getPlayer()) + .executes(context -> list(context.getSource()) )); } @@ -70,57 +70,59 @@ class SpeciesCommand { } source.sendFeedback(() -> Text.translatable("commands.race.success.other", player.getName(), race.getDisplayName()), true); } - } else if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { - player.sendMessage(Text.translatable("commands.race.permission"), false); + } else { + source.sendFeedback(() -> Text.translatable("commands.race.permission"), false); } return 0; } static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) { - Race spec = Pony.of(player).getSpecies(); + source.sendFeedback(() -> { + Race spec = Pony.of(player).getSpecies(); - String name = "commands.race.tell."; - name += isSelf ? "self" : "other"; + String name = "commands.race.tell."; + name += isSelf ? "self" : "other"; - player.sendMessage(Text.translatable(name, player.getName()) + return Text.translatable(name, player.getName()) .append(Text.translatable(spec.getTranslationKey()) - .styled(s -> s.withColor(Formatting.GOLD))), false); - + .styled(s -> s.withColor(Formatting.GOLD))); + }, false); return 0; } - static int list(PlayerEntity player) { - player.sendMessage(Text.translatable("commands.race.list"), false); + static int list(ServerCommandSource source) { + source.sendFeedback(() -> Text.translatable("commands.race.list"), false); + source.sendFeedback(() -> { + MutableText message = Text.literal(""); - MutableText message = Text.literal(""); - - boolean first = true; - for (Race i : Race.REGISTRY) { - if (i.availability().isGrantable() && !i.isUnset() && i.isPermitted(player)) { - message.append(Text.literal((!first ? "\n" : "") + " - ")); - message.append(i.getDisplayName()); - first = false; + boolean first = true; + for (Race i : Race.REGISTRY) { + if (i.availability().isGrantable() && !i.isUnset() && i.isPermitted(source.getPlayer())) { + message.append(Text.literal((!first ? "\n" : "") + " - ")); + message.append(i.getDisplayName()); + first = false; + } } - } - player.sendMessage(message.styled(s -> s.withColor(Formatting.GOLD)), false); + return message.styled(s -> s.withColor(Formatting.GOLD)); + }, false); return 0; } - static int describe(PlayerEntity player, Race species) { + static int describe(ServerCommandSource source, Race species) { Identifier id = Race.REGISTRY.getId(species); for (String category : new String[] { "goods", "bads" }) { - player.sendMessage(Text.translatable( + source.sendFeedback(() -> Text.translatable( String.format("gui.unicopia.tribe_selection.confirm.%s.%d.%s.%s", category), species.getAltDisplayName() ), false); for (int i = 1; i < 5; i++) { String line = String.format("gui.unicopia.tribe_selection.confirm.%s.%d.%s.%s", category, i, id.getNamespace(), id.getPath()); - player.sendMessage(Text.translatable(line).styled(s -> s.withColor(category.equals("goods") ? Formatting.YELLOW : Formatting.RED)), false); + source.sendFeedback(() -> Text.translatable(line).styled(s -> s.withColor(category.equals("goods") ? Formatting.YELLOW : Formatting.RED)), false); } } diff --git a/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java b/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java index 04bcf078..560eaecc 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java @@ -13,6 +13,7 @@ import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.*; import net.minecraft.util.Hand; +import net.minecraft.world.GameRules; class TraitCommand { static LiteralArgumentBuilder create() { @@ -78,7 +79,9 @@ class TraitCommand { float gravity = iplayer.getPhysics().getGravityModifier(); if (source.getPlayer() == player) { - player.sendMessage(Text.translatable(translationKey, gravity), false); + if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { + player.sendMessage(Text.translatable(translationKey, gravity), false); + } } else { source.sendFeedback(() -> Text.translatable(translationKey + ".other", player.getName(), gravity), true); } From fe39258cffb2c3bd8a218a74c156290bb8428ae0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:10:38 +0100 Subject: [PATCH 13/81] Fixed crash when wearing alicorn amulet. Fixes #400 --- .../minelittlepony/unicopia/entity/AttributeContainer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java index 8f94a440..85d61d88 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java @@ -26,9 +26,7 @@ public interface AttributeContainer { EntityAttributeModifier modifier = instance.getModifier(id); if (!MathHelper.approximatelyEquals(desiredValue, modifier == null ? 0 : modifier.getValue())) { - if (modifier != null) { - instance.removeModifier(modifier); - } + instance.removeModifier(id); if (desiredValue != 0) { if (permanent) { From 1b2f0ebd6b481e369da7f33e4adf038f6ba2e39e Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:11:19 +0100 Subject: [PATCH 14/81] Fixed crash when disguised as a mob whilst wearing an amulet. Fixes #401 --- .../unicopia/client/render/AmuletFeatureRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java index 99bce334..d5a2ffbf 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java @@ -49,7 +49,9 @@ public class AmuletFeatureRenderer implements AccessoryF VertexConsumer consumer = ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayer.getArmorCutoutNoCull(texture), false, false); - model.setAngles(entity, context.getModel()); + if (context.getModel() instanceof BipedEntityModel) { + model.setAngles(entity, context.getModel()); + } model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1); } } From 512ae4d126d11a2c708916dea92e3ddbf4569cb7 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:26:07 +0100 Subject: [PATCH 15/81] Fixed bat screech effect position when ponified. Fixes #399 --- .../com/minelittlepony/unicopia/ability/ScreechAbility.java | 5 ++++- .../minelittlepony/unicopia/client/minelittlepony/Main.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java index 55b9c393..52bd6e66 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.ability.data.Numeric; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.advancement.UCriteria; +import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; @@ -126,8 +127,10 @@ public class ScreechAbility implements Ability { @Override public void coolDown(Pony player, AbilitySlot slot) { + Vec3d eyePos = player.asEntity().getPos().add(0, MineLPDelegate.getInstance().getPonyHeight(player.asEntity()) * 0.8, 0); + for (int i = 0; i < 20; i++) { - player.addParticle(ParticleTypes.BUBBLE_POP, player.asEntity().getEyePos(), + player.addParticle(ParticleTypes.BUBBLE_POP, eyePos, VecHelper.supply(() -> (player.asWorld().getRandom().nextGaussian() - 0.5) * 0.3) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java index 229fb3ed..4abe27c4 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java @@ -117,7 +117,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer { @Override public float getPonyHeight(Entity entity) { - return super.getPonyHeight(entity) * IPony.getManager().getPony(entity).map(pony -> pony.metadata().getSize().getScaleFactor() + 0.1F).orElse(1F); + return super.getPonyHeight(entity) * IPony.getManager().getPony(entity) + .map(pony -> pony.race().isHuman() ? 1 : pony.metadata().getSize().getScaleFactor() + 0.1F) + .orElse(1F); } private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) { From 9424a3f2ba5f53123aa09c676906adeec371ded6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:43:43 +0100 Subject: [PATCH 16/81] Fix jar inventory size mismatch. Fixes #441 --- .../unicopia/block/jar/ItemsJarContents.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java index a406c3dd..62f39881 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java @@ -30,15 +30,16 @@ public record ItemsJarContents ( TileData tile, List stacks ) implements JarContents, SidedInventory { - private static final int[] SLOTS = IntStream.range(0, 16).toArray(); + private static final int MAX_SIZE = 16; + private static final int[] SLOTS = IntStream.range(0, MAX_SIZE).toArray(); public ItemsJarContents(TileData tile) { - this(tile, new ArrayList<>()); + this(tile, new ArrayList<>(MAX_SIZE)); } public ItemsJarContents(TileData tile, NbtCompound compound) { this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE)) - .limit(15) + .limit(MAX_SIZE) .collect(Collectors.toList())); } @@ -115,7 +116,7 @@ public record ItemsJarContents ( @Override public int size() { - return 15; + return MAX_SIZE; } @Override From aa7c4511e9f5c57141d3dd3f7548fee11102bcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Wed, 18 Sep 2024 00:59:15 +0100 Subject: [PATCH 17/81] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 26 ++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..50c1f090 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug +assignees: Sollace + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Steps to reproduce** +Help us figure out what you did to get this issue + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Version Information:** + - Minecraft Version: [e.g. 1.20.5] + - Mine Little Pony Version: + +**Mod Loader:** + - [ ] Fabric + - [ ] Quilt + - [ ] Neoforge (with connector) + +**Client/Server Logs** +If applicable, add log files by uploading them as attachments or put them below. + +

+``` +**Paste logs here** +``` +
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..7b2634da --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: Sollace + +--- + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here. + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Version Information:** + - Minecraft Version: [e.g. 1.20.5] + - Mine Little Pony Version: + +**Mod Loader:** + - [ ] Fabric + - [ ] Quilt + - [ ] Neoforge (with connector) From 956dbd26b9a1cadacfcfd5f09b89e364b99a1873 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 15:13:47 +0100 Subject: [PATCH 18/81] Fix the displacement spell. Fixes #456 --- .../magic/spell/PlacementControlSpell.java | 55 +++++++++---------- .../magic/spell/effect/DisplacementSpell.java | 34 ++++++++++-- .../unicopia/entity/mob/CastSpellEntity.java | 9 ++- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java index 9eee830f..339deac6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java @@ -77,39 +77,38 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel @Override public boolean apply(Caster caster) { - if (delegate == null) { - return false; - } - boolean result = super.apply(caster); - if (result) { - if (dimension.isEmpty()) { - setDimension(caster.asWorld().getRegistryKey()); - } - if (position.isEmpty()) { - setPosition(caster.asEntity().getPos()); - } - if (delegate instanceof PlacementDelegate) { - ((PlacementDelegate)delegate).onPlaced(caster, this); - } - - CastSpellEntity entity = new CastSpellEntity(caster.asWorld(), caster, this); - - Vec3d pos = position.get(); - Vec3d rot = orientation.orElse(Vec3d.ZERO); - - entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); - entity.getWorld().spawnEntity(entity); - - placedEntityId = entity.getUuid(); - } - return result; + return delegate != null && super.apply(caster); } @Override public boolean tick(Caster source, Situation situation) { - if (!source.isClient() && getConnection(source) == null) { - setDead(); + if (!source.isClient()) { + + if (placedEntityId == null) { + if (dimension.isEmpty()) { + setDimension(source.asWorld().getRegistryKey()); + } + if (position.isEmpty()) { + setPosition(source.asEntity().getPos()); + } + System.out.println("Creating placed spell"); + CastSpellEntity entity = new CastSpellEntity(source.asWorld(), source, this); + + Vec3d pos = position.get(); + Vec3d rot = orientation.orElse(Vec3d.ZERO); + + entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); + entity.getWorld().spawnEntity(entity); + + placedEntityId = entity.getUuid(); + setDirty(); + } else { + if (getConnection(source) == null) { + setDead(); + } + } } + return !isDead(); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 1afef18f..974da9de 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -18,13 +18,13 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.Vec3d; -public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener { +public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.HitListener { private static final SpellAttribute DAMAGE_TO_TARGET = SpellAttribute.create(SpellAttributeType.DAMAGE_TO_TARGET, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.BLOOD, blood -> blood); static final TooltipFactory TOOLTIP = DAMAGE_TO_TARGET; - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); private int ticks = 10; @@ -34,7 +34,7 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public Spell prepareForCast(Caster caster, CastingMethod method) { - return toPlaceable(); + return method.isIndirectCause() ? this : toPlaceable(); } @Override @@ -43,14 +43,23 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro originator.asEntity().setGlowing(true); + if (situation == Situation.PROJECTILE) { + return !isDead(); + } + ticks--; if (originator.isClient()) { return !isDead() || ticks >= -10; } - if (ticks == 0) { - target.ifPresent(originator.asWorld(), target -> apply(originator, target)); + if (!originator.isClient()) { + target.ifPresent(originator.asWorld(), target -> { + target.setGlowing(true); + if (ticks == 0) { + apply(originator, target); + } + }); } return ticks >= -10; @@ -58,7 +67,18 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { - Caster.of(projectile.getMaster()).ifPresent(originator -> apply(originator, hit.getEntity())); + HitListener.super.onImpact(projectile, hit); + Caster.of(projectile.getMaster()).ifPresent(originator -> { + apply(originator, hit.getEntity()); + }); + } + + @Override + public void onImpact(MagicProjectileEntity projectile) { + if (projectile.getMaster() instanceof Entity owner) { + owner.setGlowing(false); + } + target.ifPresent(projectile.asWorld(), e -> e.setGlowing(false)); } private void apply(Caster originator, Entity target) { @@ -107,11 +127,13 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.putInt("ticks", ticks); + compound.put("target", target.toNBT()); } @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); ticks = compound.getInt("ticks"); + target.fromNBT(compound.getCompound("target")); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java index fbca955c..34216ea4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java @@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.SpellSlots; import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell.PlacementDelegate; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.EntityPhysics; import com.minelittlepony.unicopia.entity.EntityReference; @@ -70,8 +71,12 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster type, World world) { From 8c560e3ff31ad374b3c3800a804e010f9918049b Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 16:52:44 +0100 Subject: [PATCH 19/81] Fixed amulet rendering when trinkets is not installed. Closes #455 --- build.gradle | 7 ++++++- gradle.properties | 1 + lib/trinkets-dummy-3.8.0.jar | Bin 0 -> 235614 bytes .../compat/trinkets/TrinketsDelegate.java | 2 +- .../unicopia/item/AmuletItem.java | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 lib/trinkets-dummy-3.8.0.jar diff --git a/build.gradle b/build.gradle index 8752d140..de730eec 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,12 @@ dependencies { include "com.sollace:Romanizer:Romanizer:1.0.2" modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}" - modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" + + if (project.use_trinkets == '1') { + modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" + } else { + modCompileOnly "dev.emi:trinkets-dummy:${project.trinkets_version}" + } modImplementation "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" diff --git a/gradle.properties b/gradle.properties index 7018784c..25ccc1c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,6 +30,7 @@ org.gradle.daemon=false nodium_version=1.1.0+1.20 # Testing + use_trinkets=1 use_pehkui=0 use_sodium=1 diff --git a/lib/trinkets-dummy-3.8.0.jar b/lib/trinkets-dummy-3.8.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..1e65318dcb687edd2e22bddb1464f8f1fb7dba75 GIT binary patch literal 235614 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%0ATS$4NZ{l@p%Kp? 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⋘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

-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 M;eNOzm`UjP6A literal 0 HcmV?d00001 diff --git a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java index f19d592a..c73f5d46 100644 --- a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java @@ -127,7 +127,7 @@ public interface TrinketsDelegate { } record EquippedStack(ItemStack stack, Runnable sendUpdate, Consumer breakStatusSender) { - public static EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {}); + public static final EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {}); EquippedStack(LivingEntity entity, EquipmentSlot slot) { this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot)); diff --git a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java index 8e0673f7..a434863f 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java @@ -101,7 +101,7 @@ public class AmuletItem extends WearableItem implements ChargeableItem { } public static TrinketsDelegate.EquippedStack get(LivingEntity entity) { - return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE) + return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, stack -> stack.getItem() instanceof AmuletItem) .findFirst() .orElse(TrinketsDelegate.EquippedStack.EMPTY); } From 7b5a7682c4c926cadfb8a47eaae1392310ede00b Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 17:33:13 +0100 Subject: [PATCH 20/81] Fixed bubble spell offset from entity center. Fixes #457 --- .../render/spell/BubbleSpellRenderer.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java index 48f0dbb9..f7fe2241 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java @@ -19,19 +19,22 @@ public class BubbleSpellRenderer extends SpellRenderer { super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); matrices.push(); - double height = caster.asEntity().getEyeY() - caster.getOriginVector().y; - matrices.translate(0, height * 0.5F, 0); + double height = caster.asEntity().getEyeY() - caster.getOriginVector().getY(); - float radius = spell.getRadius(tickDelta) * 0.7F; - VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicNoColor()); + float radius = spell.getRadius(tickDelta) * 1.5F; + + matrices.translate(0, radius * 0.5F + height, 0); + + VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicShield()); Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity(); matrices.push(); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-45)); - matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(45 + cameraEntity.getYaw(tickDelta))); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta))); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90)); + matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(cameraEntity.getYaw(tickDelta) - 25)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-cameraEntity.getPitch(tickDelta))); + new SphereModel(40, 40, DrawableUtil.PI * 0.25F).render(matrices, buffer, light, 0, radius - 0.1F, 0.9F, 0.9F, 1, 0.3F); matrices.pop(); From 2458471fdd0291dca0fa76455212a218312c1eb0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:02:59 +0100 Subject: [PATCH 21/81] Fixed rendering wackyness when the timer is displayed for timed spells --- .../client/render/spell/SpellRenderer.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java index a1171b7c..be29e501 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.client.render.spell; +import org.joml.Quaternionf; + import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; @@ -13,6 +15,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityPose; +import net.minecraft.entity.LivingEntity; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; @@ -37,6 +41,8 @@ public class SpellRenderer { private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, int light, float tickDelta, float animationProgress) { matrices.push(); + float scale = 1/8F; + matrices.scale(scale, scale, scale); transformGemstone(matrices, vertices, spell, caster, animationProgress); matrices.push(); @@ -46,6 +52,22 @@ public class SpellRenderer { matrices.pop(); if (spell instanceof TimedSpell timed) { + if (caster.asEntity() instanceof LivingEntity l && !l.isInPose(EntityPose.SLEEPING)) { + float bodyYaw = MathHelper.lerpAngleDegrees(tickDelta, l.prevBodyYaw, l.bodyYaw); + float headYaw = MathHelper.lerpAngleDegrees(tickDelta, l.prevHeadYaw, l.headYaw); + float yawDifference = headYaw - bodyYaw; + if (l.hasVehicle() && l.getVehicle() instanceof LivingEntity vehicle) { + bodyYaw = MathHelper.lerpAngleDegrees(tickDelta, vehicle.prevBodyYaw, vehicle.bodyYaw); + yawDifference = headYaw - bodyYaw; + float clampedYawDifference = MathHelper.clamp(MathHelper.wrapDegrees(yawDifference), -85, 85); + bodyYaw = headYaw - clampedYawDifference; + if (clampedYawDifference * clampedYawDifference > 2500) { + bodyYaw += clampedYawDifference * 0.2F; + } + yawDifference = headYaw - bodyYaw; + } + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - bodyYaw)); + } renderCountdown(matrices, timed, tickDelta); } @@ -53,7 +75,7 @@ public class SpellRenderer { } protected void renderCountdown(MatrixStack matrices, TimedSpell spell, float tickDelta) { - matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert()); + matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert(new Quaternionf())); float radius = 0.6F; float timeRemaining = spell.getTimer().getPercentTimeRemaining(tickDelta); @@ -67,6 +89,6 @@ public class SpellRenderer { if (caster.asEntity() instanceof CastSpellEntity) { y = 1F; } - matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); + matrices.translate(0, y * 8 + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); } } From a3d5670f7ac963fefbd5c30359aaf9f5c567865c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:24:34 +0100 Subject: [PATCH 22/81] Adjust bat pony visibility. Fixes #425 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9d09beaa..cba9e735 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -597,7 +597,7 @@ public class Pony extends Living implements Copyable, Update float lightScale = light / 15F; float approachFactor = ((velocityScale + lightScale) / 2F); - if (approachFactor < (entity.isSneaking() ? 0.8F : 0.6F)) { + if (approachFactor < (entity.isSneaking() ? 0.8F : 0.3F)) { return false; } } From 55a57c3d1b2f0095328d1946c47878ed659146dc Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:35:42 +0100 Subject: [PATCH 23/81] Fix compatibility with Xaero's minimap. Fixes #437 --- src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index 590ed1e7..687bcffb 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -84,7 +84,7 @@ public class UHud { Pony pony = Pony.of(client.player); matrices.push(); - matrices.translate(0, 0, hotbarZ); + matrices.translate(0, 0, hotbarZ - 9800); renderViewEffects(pony, context, scaledWidth, scaledHeight, tickDelta); matrices.pop(); From ac1ac5d903078737f65e688b6e846a10027f2b6c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:44:25 +0100 Subject: [PATCH 24/81] Fixed heavy enchant making pegasi faster. Fixes #380 --- .../unicopia/entity/player/PlayerPhysics.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 6b729dfd..01850b5b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -377,16 +377,17 @@ public class PlayerPhysics extends EntityPhysics implements Tickab tickGrounded(); } - if (!entity.isOnGround()) { - float heavyness = 1 - EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.015F; - velocity.x /= heavyness; - 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); + + if (!entity.isOnGround()) { + float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.009F; + velocity.x /= heavyness; + velocity.z /= heavyness; + } + entity.setVelocity(velocity.toImmutable()); if (isFlying() && !entity.isFallFlying() && !pony.getAcrobatics().isHanging() && pony.isClient()) { From 68146c4f8cd0f135db13aa7a49b6327a48a40df0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:17:40 +0100 Subject: [PATCH 25/81] Set tribe swap damage type to bypass things that normally block damage. May help with #453 --- .../unicopia/datagen/providers/tag/UDamageTypeProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java index a257ccb4..2c8779f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java @@ -35,9 +35,13 @@ public class UDamageTypeProvider extends FabricTagProvider { UDamageTypes.EXHAUSTION, UDamageTypes.GAVITY_WELL_RECOIL, UDamageTypes.ALICORN_AMULET, UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, UDamageTypes.BAT_SCREECH, UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING, UDamageTypes.STEAMROLLER, UDamageTypes.RAINBOOM, - UDamageTypes.SUN, UDamageTypes.SUNLIGHT, UDamageTypes.PETRIFIED + UDamageTypes.SUN, UDamageTypes.SUNLIGHT, UDamageTypes.PETRIFIED, UDamageTypes.TRIBE_SWAP ); getOrCreateTagBuilder(DamageTypeTags.BYPASSES_INVULNERABILITY).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_COOLDOWN).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_EFFECTS).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_RESISTANCE).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_ENCHANTMENTS).add(UDamageTypes.TRIBE_SWAP); getOrCreateTagBuilder(DamageTypeTags.BYPASSES_SHIELD).add( UDamageTypes.EXHAUSTION, UDamageTypes.BAT_SCREECH, UDamageTypes.ALICORN_AMULET, UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING, From 72615aac95c97053e0ad432e5da4f09a28e09072 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:19:52 +0100 Subject: [PATCH 26/81] Sunglasses can now be broken by a warden's sonic boom, falling blocks, anvils, explosions, and flying into walls. Closes #423 --- .../datagen/providers/tag/UDamageTypeProvider.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java index 2c8779f3..1506283c 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; import net.minecraft.entity.damage.DamageType; +import net.minecraft.entity.damage.DamageTypes; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.registry.tag.DamageTypeTags; @@ -25,7 +26,11 @@ public class UDamageTypeProvider extends FabricTagProvider { ).forceAddTag(DamageTypeTags.IS_FALL).forceAddTag(DamageTypeTags.IS_FREEZING).forceAddTag(DamageTypeTags.IS_LIGHTNING).forceAddTag(DamageTypeTags.IS_PROJECTILE); getOrCreateTagBuilder(UTags.DamageTypes.FROM_ROCKS).add(UDamageTypes.ROCK); getOrCreateTagBuilder(UTags.DamageTypes.FROM_HORSESHOES).add(UDamageTypes.HORSESHOE); - getOrCreateTagBuilder(UTags.DamageTypes.BREAKS_SUNGLASSES).add(UDamageTypes.BAT_SCREECH, UDamageTypes.RAINBOOM); + getOrCreateTagBuilder(UTags.DamageTypes.BREAKS_SUNGLASSES).add( + UDamageTypes.BAT_SCREECH, UDamageTypes.RAINBOOM, + DamageTypes.FLY_INTO_WALL, DamageTypes.FALLING_ANVIL, DamageTypes.FALLING_BLOCK, + DamageTypes.SONIC_BOOM + ).forceAddTag(DamageTypeTags.IS_EXPLOSION); getOrCreateTagBuilder(DamageTypeTags.AVOIDS_GUARDIAN_THORNS).add( UDamageTypes.EXHAUSTION, UDamageTypes.ALICORN_AMULET, UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, From 3f9d26f4b491ffc839a34c860a00aeb942028253 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:35:45 +0100 Subject: [PATCH 27/81] Why is gradle's compiler so stupid? Can ANYONE tell me why gradle's compiler is so stupid!? --- .../ability/magic/spell/effect/DisplacementSpell.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 974da9de..d9659de6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -75,8 +75,8 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public void onImpact(MagicProjectileEntity projectile) { - if (projectile.getMaster() instanceof Entity owner) { - owner.setGlowing(false); + if (projectile.getMaster() != null) { + projectile.getMaster().setGlowing(false); } target.ifPresent(projectile.asWorld(), e -> e.setGlowing(false)); } From 37a7b08e45e7901c29a95d7257eb78935a96e381 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:51:06 +0100 Subject: [PATCH 28/81] Add support for serene seasons. Closes #386 --- .../providers/tag/SereneSeasonsTags.java | 32 +++++++++++++++++++ .../providers/tag/UBlockTagProvider.java | 25 +++++++++++++++ .../providers/tag/UItemTagProvider.java | 5 +++ 3 files changed, 62 insertions(+) create mode 100644 src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java new file mode 100644 index 00000000..100dcc99 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java @@ -0,0 +1,32 @@ +package com.minelittlepony.unicopia.datagen.providers.tag; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; + +public interface SereneSeasonsTags { + interface Items { + TagKey AUTUMN_CROPS = item("autumn_crops"); + TagKey WINTER_CROPS = item("winter_crops"); + TagKey SPRING_CROPS = item("spring_crops"); + TagKey SUMMER_CROPS = item("summer_crops"); + + private static TagKey item(String name) { + return TagKey.of(RegistryKeys.ITEM, new Identifier("sereneseasons", name)); + } + } + + interface Blocks { + TagKey AUTUMN_CROPS = block("autumn_crops"); + TagKey WINTER_CROPS = block("winter_crops"); + TagKey SPRING_CROPS = block("spring_crops"); + TagKey SUMMER_CROPS = block("summer_crops"); + + private static TagKey block(String name) { + return TagKey.of(RegistryKeys.BLOCK, new Identifier("sereneseasons", name)); + } + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java index 66ea54f0..b741612e 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.server.world.Tree; +import com.minelittlepony.unicopia.server.world.UTreeGen; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; @@ -103,6 +104,30 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider { ).forceAddTag(TagKey.of(RegistryKeys.BLOCK, new Identifier("c", "concrete_powders"))); getOrCreateTagBuilder(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY).add(Blocks.GRASS_BLOCK); + addSeasonalCrops(); + } + + private void addSeasonalCrops() { + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.AUTUMN_CROPS).add( + UBlocks.GREEN_APPLE_LEAVES, UBlocks.GREEN_APPLE_SPROUT, UTreeGen.GREEN_APPLE_TREE.sapling().get(), + UBlocks.SOUR_APPLE_LEAVES, UBlocks.SOUR_APPLE_SPROUT, UTreeGen.SOUR_APPLE_TREE.sapling().get(), + UBlocks.OATS_CROWN, UBlocks.OATS_STEM, UBlocks.OATS, + UBlocks.ROCKS + ); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.WINTER_CROPS).add(UBlocks.ROCKS); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.SPRING_CROPS).add( + UBlocks.SWEET_APPLE_LEAVES, UBlocks.SWEET_APPLE_SPROUT, UTreeGen.SWEET_APPLE_TREE.sapling().get(), + UBlocks.GOLDEN_OAK_LEAVES, UBlocks.GOLDEN_OAK_SPROUT, UTreeGen.GOLDEN_APPLE_TREE.sapling().get(), + UBlocks.PALM_LEAVES, UBlocks.BANANAS, UTreeGen.BANANA_TREE.sapling().get(), + UBlocks.PINEAPPLE, + UBlocks.ROCKS + ); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.SUMMER_CROPS).add( + UBlocks.SWEET_APPLE_LEAVES, UBlocks.SWEET_APPLE_SPROUT, UTreeGen.SWEET_APPLE_TREE.sapling().get(), + UBlocks.MANGO_LEAVES, UTreeGen.MANGO_TREE.sapling().get(), + UBlocks.OATS_CROWN, UBlocks.OATS_STEM, UBlocks.OATS, + UBlocks.ROCKS + ); } private void addFruitTrees() { diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java index 44d1db03..9e579480 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java @@ -175,6 +175,11 @@ public class UItemTagProvider extends FabricTagProvider.ItemTagProvider { copy(UTags.Blocks.CLOUD_STAIRS, UTags.Items.CLOUD_STAIRS); copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS); copy(UTags.Blocks.CHITIN_BLOCKS, UTags.Items.CHITIN_BLOCKS); + + copy(SereneSeasonsTags.Blocks.AUTUMN_CROPS, SereneSeasonsTags.Items.AUTUMN_CROPS); + copy(SereneSeasonsTags.Blocks.WINTER_CROPS, SereneSeasonsTags.Items.WINTER_CROPS); + copy(SereneSeasonsTags.Blocks.SPRING_CROPS, SereneSeasonsTags.Items.SPRING_CROPS); + copy(SereneSeasonsTags.Blocks.SUMMER_CROPS, SereneSeasonsTags.Items.SUMMER_CROPS); } private void exportForagingTags() { From 2016b7dd84845d5947756bc9d38209a3226ef890 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:24:28 +0100 Subject: [PATCH 29/81] Fixed spells not executing their on destroy handlers --- .../minelittlepony/unicopia/ability/magic/MultiSpellSlot.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index e38184b7..5a1d9788 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -114,8 +114,10 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { } else { Spell s = spell.get(); if (s != null) { - s.setDead(); s.tickDying(owner); + if (s.isDead()) { + s.destroy(owner); + } } } } From dc3367806255f38f65ff7f61cd4f47f2257fb4aa Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:25:29 +0100 Subject: [PATCH 30/81] Fix background rendering in the dismiss spell screen --- .../unicopia/client/gui/DismissSpellScreen.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index cddf13b9..23b90dc6 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,6 +101,11 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } + @Override + public void renderInGameBackground(DrawContext context) { + + } + @Override public boolean shouldPause() { return false; From 420f78eaaf9ec7806da010f7f46701f224e5fa61 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:27:53 +0100 Subject: [PATCH 31/81] Track which spells are active on which blocks to make tile-by-tile interactions easier. Requireed by #412 --- .../com/minelittlepony/unicopia/Unicopia.java | 2 + .../unicopia/server/world/Ether.java | 59 +++++++++++-- .../unicopia/server/world/WorldOverlay.java | 2 +- .../unicopia/server/world/chunk/Chunk.java | 64 +++++++++++++++ .../server/world/chunk/PositionalDataMap.java | 63 ++++++++++++++ .../unicopia/server/world/chunk/Section.java | 82 +++++++++++++++++++ 6 files changed, 264 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index 8142560d..a6057f85 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -31,6 +31,7 @@ import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.server.world.NocturnalSleepManager; import com.minelittlepony.unicopia.server.world.UGameRules; import com.minelittlepony.unicopia.server.world.UWorldGen; @@ -71,6 +72,7 @@ public class Unicopia implements ModInitializer { ((BlockDestructionManager.Source)w).getDestructionManager().tick(); ZapAppleStageStore.get(w).tick(); WeatherConditions.get(w).tick(); + Ether.get(w).tick(); if (Debug.SPELLBOOK_CHAPTERS) { SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer()); } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java index 840e66fa..08c6a9a2 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java @@ -13,14 +13,18 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.server.world.chunk.PositionalDataMap; import com.minelittlepony.unicopia.util.NbtSerialisable; +import com.minelittlepony.unicopia.util.Tickable; + import net.minecraft.nbt.*; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.PersistentState; import net.minecraft.world.World; -public class Ether extends PersistentState { +public class Ether extends PersistentState implements Tickable { private static final Identifier ID = Unicopia.id("ether"); public static Ether get(World world) { @@ -28,6 +32,7 @@ public class Ether extends PersistentState { } private final Map>>> endpoints; + private final PositionalDataMap> positionData = new PositionalDataMap<>(); private final Object locker = new Object(); @@ -70,23 +75,36 @@ public class Ether extends PersistentState { markDirty(); return new Entry<>(spell, caster); }); - if (entry.removed) { - entry.removed = false; - markDirty(); - } + if (entry.spell.get() != spell) { entry.spell = new WeakReference<>(spell); markDirty(); } + if (entry.removed) { + entry.removed = false; + positionData.update(entry); + markDirty(); + } return entry; } } + @Override + public void tick() { + endpoints.values().forEach(byType -> { + byType.values().forEach(entries -> { + entries.values().forEach(Entry::update); + }); + }); + } + public void remove(SpellType spellType, UUID entityId) { synchronized (locker) { endpoints.computeIfPresent(spellType.getId(), (typeId, entries) -> { - if (entries.remove(entityId) != null) { + Map> data = entries.remove(entityId); + if (data != null) { markDirty(); + data.values().forEach(positionData::remove); } return entries.isEmpty() ? null : entries; }); @@ -150,6 +168,10 @@ public class Ether extends PersistentState { return false; } + public Set> getAtPosition(BlockPos pos) { + return world.isClient() ? Set.of() : positionData.getState(pos); + } + private void pruneNodes() { this.endpoints.values().removeIf(entities -> { entities.values().removeIf(spells -> { @@ -160,7 +182,7 @@ public class Ether extends PersistentState { }); } - public class Entry implements NbtSerialisable { + public class Entry implements PositionalDataMap.Hotspot, NbtSerialisable { public final EntityReference entity; @Nullable @@ -176,6 +198,9 @@ public class Ether extends PersistentState { private final Set claimants = new HashSet<>(); + private BlockPos currentPos = BlockPos.ORIGIN; + private BlockPos previousPos = BlockPos.ORIGIN; + private Entry(NbtElement nbt) { this.entity = new EntityReference<>(); this.spell = new WeakReference<>(null); @@ -186,6 +211,15 @@ public class Ether extends PersistentState { this.entity = new EntityReference<>(caster.asEntity()); this.spell = new WeakReference<>(spell); spellId = spell.getUuid(); + update(); + } + + void update() { + previousPos = currentPos; + currentPos = entity.getTarget().map(t -> BlockPos.ofFloored(t.pos())).orElse(BlockPos.ORIGIN); + if (!currentPos.equals(previousPos)) { + positionData.update(this); + } } public boolean hasChanged() { @@ -216,6 +250,13 @@ public class Ether extends PersistentState { markDirty(); } + + @Override + public BlockPos getCenter() { + return currentPos; + } + + @Override public float getRadius() { return radius; } @@ -223,6 +264,9 @@ public class Ether extends PersistentState { public void setRadius(float radius) { if (!MathHelper.approximatelyEquals(this.radius, radius)) { this.radius = radius; + if ((int)radius != (int)this.radius) { + positionData.update(this); + } changed.set(true); } markDirty(); @@ -247,6 +291,7 @@ public class Ether extends PersistentState { public void markDead() { Unicopia.LOGGER.debug("Marking " + entity.getTarget().orElse(null) + " as dead"); removed = true; + positionData.remove(this); claimants.clear(); markDirty(); } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java b/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java index 8d4512b4..4c5212a9 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java @@ -94,7 +94,7 @@ public class WorldOverlay extends PersistentState } private Chunk getChunk(BlockPos pos) { - return chunks.computeIfAbsent(new ChunkPos(pos).toLong(), Chunk::new); + return chunks.computeIfAbsent(ChunkPos.toLong(pos), Chunk::new); } public void setState(BlockPos pos, @Nullable T state) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java new file mode 100644 index 00000000..d59919db --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java @@ -0,0 +1,64 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.ChunkSectionPos; + +public class Chunk { + private final Long2ObjectMap> sections = new Long2ObjectOpenHashMap<>(); + private final Map>> entryToSections = new WeakHashMap<>(); + + Chunk(long pos) { } + + public synchronized Set getState(BlockPos pos) { + Section section = sections.get(ChunkSectionPos.getSectionCoord(pos.getY())); + return section == null ? Set.of() : section.getState(pos); + } + + public synchronized boolean remove(T entry) { + Set> sections = entryToSections.remove(entry); + if (sections != null) { + sections.forEach(section -> { + if (section.remove(entry) && section.isEmpty()) { + this.sections.remove(section.pos); + } + }); + return true; + } + return false; + } + + public synchronized boolean update(T entry, Box entryBox) { + Set> oldSections = entryToSections.get(entry); + Set> newSections = getIntersectingSections(entryBox); + if (oldSections != null) { + oldSections.forEach(section -> { + if (!newSections.contains(section) && section.remove(entry) && section.isEmpty()) { + this.sections.remove(section.pos); + } + }); + } + newSections.forEach(chunk -> chunk.update(entry, entryBox)); + entryToSections.put(entry, newSections); + return true; + } + + private Set> getIntersectingSections(Box entryBox) { + Set> sections = new HashSet<>(); + + int minY = ChunkSectionPos.getSectionCoord(entryBox.minY); + int maxY = ChunkSectionPos.getSectionCoord(entryBox.maxY); + for (int y = minY; y <= maxY; y++) { + sections.add(this.sections.computeIfAbsent(y, Section::new)); + } + + return sections; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java new file mode 100644 index 00000000..eb2ee335 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java @@ -0,0 +1,63 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.util.math.MathHelper; + +public class PositionalDataMap { + private final Long2ObjectMap> chunks = new Long2ObjectOpenHashMap<>(); + private final Map>> entryToChunks = new WeakHashMap<>(); + + public Set getState(BlockPos pos) { + Chunk chunk = chunks.get(ChunkPos.toLong(pos)); + return chunk == null ? Set.of() : chunk.getState(pos); + } + + public void remove(T entry) { + Set> chunks = entryToChunks.remove(entry); + if (chunks != null) { + chunks.forEach(chunk -> chunk.remove(entry)); + } + } + + public void update(T entry) { + Box entryBox = new Box(entry.getCenter()).expand(MathHelper.ceil(entry.getRadius())); + Set> oldChunks = entryToChunks.get(entry); + Set> newChunks = getIntersectingChunks(entryBox); + if (oldChunks != null) { + oldChunks.forEach(chunk -> chunk.remove(entry)); + } + newChunks.forEach(chunk -> chunk.update(entry, entryBox)); + entryToChunks.put(entry, newChunks); + } + + private Set> getIntersectingChunks(Box entryBox) { + int minX = ChunkSectionPos.getSectionCoord(entryBox.minX); + int maxX = ChunkSectionPos.getSectionCoord(entryBox.maxX); + int minZ = ChunkSectionPos.getSectionCoord(entryBox.minZ); + int maxZ = ChunkSectionPos.getSectionCoord(entryBox.maxZ); + + Set> chunks = new HashSet<>(); + for (int x = minX; x <= maxX; x++) { + for (int z = minZ; z <= maxZ; z++) { + chunks.add(this.chunks.computeIfAbsent(ChunkPos.toLong(x, z), Chunk::new)); + } + } + return chunks; + } + + public interface Hotspot { + float getRadius(); + + BlockPos getCenter(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java new file mode 100644 index 00000000..7024acdc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java @@ -0,0 +1,82 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; + +public class Section { + private final Set entries = weakSet(); + private Set[] states; + + final long pos; + + public Section(long pos) { + this.pos = pos; + } + + public boolean isEmpty() { + return entries.isEmpty(); + } + + public boolean remove(T entry) { + if (entries.remove(entry)) { + states = null; + return true; + } + return false; + } + + public boolean update(T entry, Box box) { + entries.add(entry); + states = null; + return true; + } + + @SuppressWarnings("unchecked") + public Set getState(BlockPos pos) { + int localPos = toLocalIndex(pos); + if (states == null) { + states = new Set[16 * 16 * 16]; + } + Set state = states[localPos]; + return state == null ? (states[localPos] = calculateState(pos)) : state; + } + + private Set calculateState(BlockPos pos) { + Set state = weakSet(); + + for (T entry : entries) { + BlockPos center = entry.getCenter(); + int radius = MathHelper.ceil(entry.getRadius()); + + if (pos.equals(center) + || (isInRange(pos.getX(), center.getX(), radius) + && isInRange(pos.getZ(), center.getZ(), radius) + && isInRange(pos.getY(), center.getY(), radius) + && center.isWithinDistance(pos, radius))) { + state.add(entry); + } + } + + return state; + } + + static boolean isInRange(int value, int center, int radius) { + return value >= center - radius && value <= center + radius; + } + + static int toLocalIndex(BlockPos pos) { + int x = pos.getX() % 16; + int y = pos.getY() % 16; + int z = pos.getZ() % 16; + return x + (y * 16) + (z * 16 * 16); + } + + static Set weakSet() { + return Collections.newSetFromMap(new WeakHashMap<>()); + } +} From 92ad502fa7f8db0efb218876f7a568777a788e22 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 23:26:23 +0100 Subject: [PATCH 32/81] Set the spell as dead when removing it --- .../minelittlepony/unicopia/ability/magic/MultiSpellSlot.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index 5a1d9788..816047c9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -114,6 +114,7 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { } else { Spell s = spell.get(); if (s != null) { + s.setDead(); s.tickDying(owner); if (s.isDead()) { s.destroy(owner); From 469aaeecd1612691d2841e1faee718a9606c1b83 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:40:20 +0100 Subject: [PATCH 33/81] Remove Spell#isDirty and Spell#setDirty --- .../ability/magic/MultiSpellSlot.java | 2 +- .../magic/spell/AbstractDelegatingSpell.java | 12 ---- .../magic/spell/AbstractDisguiseSpell.java | 2 +- .../ability/magic/spell/EmptySpell.java | 8 --- .../magic/spell/PlacementControlSpell.java | 64 +++++++++---------- .../unicopia/ability/magic/spell/Spell.java | 12 ---- .../ability/magic/spell/SpellReference.java | 5 -- .../magic/spell/effect/AbstractSpell.java | 14 ---- .../magic/spell/effect/AttractiveSpell.java | 6 +- .../magic/spell/effect/AwkwardSpell.java | 3 +- .../magic/spell/effect/BubbleSpell.java | 9 +-- .../magic/spell/effect/FeatherFallSpell.java | 3 +- .../magic/spell/effect/FireBoltSpell.java | 2 +- .../magic/spell/effect/LightSpell.java | 3 +- .../magic/spell/effect/MimicSpell.java | 3 +- .../magic/spell/effect/PortalSpell.java | 2 +- .../render/EntityReplacementManager.java | 4 -- .../unicopia/entity/behaviour/Disguise.java | 3 - .../entity/behaviour/EntityAppearance.java | 46 ++++++++++++- .../entity/behaviour/SheepBehaviour.java | 2 +- .../network/track/TrackableDataType.java | 10 +++ .../util/serialization/PacketCodec.java | 17 ++++- 22 files changed, 114 insertions(+), 118 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index 816047c9..50cb5902 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -131,7 +131,7 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { return hasValue ? Status.NEW : Status.REMOVED; } - return spell.hasDirtySpell() ? Status.UPDATED : Status.DEFAULT; + return Status.DEFAULT; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java index 78373b5a..9ff86367 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java @@ -80,18 +80,6 @@ public abstract class AbstractDelegatingSpell implements Spell { return getOrEmpty().isDying(); } - @Deprecated - @Override - public boolean isDirty() { - return delegate.hasDirtySpell(); - } - - @Deprecated - @Override - public void setDirty() { - getOrEmpty().setDirty(); - } - @Override public boolean isHidden() { return getOrEmpty().isHidden(); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java index 41e7c996..b4e6ad08 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java @@ -20,7 +20,7 @@ import net.minecraft.nbt.NbtCompound; */ public abstract class AbstractDisguiseSpell extends AbstractSpell implements Disguise, ProjectileImpactListener { - private final EntityAppearance disguise = new EntityAppearance(); + private final EntityAppearance disguise = dataTracker.startTracking(new EntityAppearance()); public AbstractDisguiseSpell(CustomisedSpellType type) { super(type); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java index 89b3f986..f4dca074 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java @@ -44,11 +44,6 @@ public final class EmptySpell implements Spell { return false; } - @Override - public boolean isDirty() { - return false; - } - @Override public boolean tick(Caster caster, Situation situation) { return false; @@ -57,9 +52,6 @@ public final class EmptySpell implements Spell { @Override public void tickDying(Caster caster) { } - @Override - public void setDirty() { } - @Override public boolean isHidden() { return true; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java index 339deac6..e3f31a03 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java @@ -9,6 +9,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.AbstractSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import com.minelittlepony.unicopia.network.track.DataTracker; +import com.minelittlepony.unicopia.network.track.TrackableDataType; import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.NbtSerialisable; @@ -21,12 +23,10 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class PlacementControlSpell extends AbstractSpell implements OrientedSpell { - @Nullable - private UUID placedEntityId; - - private Optional> dimension = Optional.empty(); - private Optional position = Optional.empty(); - private Optional orientation = Optional.empty(); + private final DataTracker.Entry placedEntityId = dataTracker.startTracking(TrackableDataType.UUID, null); + private final DataTracker.Entry>> dimension = dataTracker.startTracking(TrackableDataType.ofRegistryKey(), Optional.empty()); + private final DataTracker.Entry> position = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty()); + private final DataTracker.Entry> orientation = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty()); @Nullable private Spell delegate; @@ -46,26 +46,23 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel } public Optional getPosition() { - return position; + return position.get(); } public void setDimension(RegistryKey dimension) { - this.dimension = Optional.of(dimension); - setDirty(); + this.dimension.set(Optional.of(dimension)); } public void setPosition(Vec3d position) { - this.position = Optional.of(position); - setDirty(); + this.position.set(Optional.of(position)); } @Override public void setOrientation(Caster caster, float pitch, float yaw) { - this.orientation = Optional.of(new Vec3d(pitch, yaw, 0)); + this.orientation.set(Optional.of(new Vec3d(pitch, yaw, 0))); if (delegate instanceof OrientedSpell o) { o.setOrientation(caster, pitch, yaw); } - setDirty(); if (!caster.isClient()) { var entry = getConnection(caster); if (entry != null) { @@ -84,24 +81,23 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel public boolean tick(Caster source, Situation situation) { if (!source.isClient()) { - if (placedEntityId == null) { - if (dimension.isEmpty()) { + if (placedEntityId.get() == null) { + if (dimension.get().isEmpty()) { setDimension(source.asWorld().getRegistryKey()); } - if (position.isEmpty()) { + if (getPosition().isEmpty()) { setPosition(source.asEntity().getPos()); } - System.out.println("Creating placed spell"); + CastSpellEntity entity = new CastSpellEntity(source.asWorld(), source, this); - Vec3d pos = position.get(); - Vec3d rot = orientation.orElse(Vec3d.ZERO); + Vec3d pos = getPosition().get(); + Vec3d rot = orientation.get().orElse(Vec3d.ZERO); entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); entity.getWorld().spawnEntity(entity); - placedEntityId = entity.getUuid(); - setDirty(); + placedEntityId.set(entity.getUuid()); } else { if (getConnection(source) == null) { setDead(); @@ -114,24 +110,24 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel @Nullable private Ether.Entry getConnection(Caster source) { - return delegate == null || placedEntityId == null ? null : getWorld(source) - .map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId, delegate.getUuid())) + return delegate == null || placedEntityId.get() == null ? null : getWorld(source) + .map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId.get(), delegate.getUuid())) .orElse(null); } private Optional getWorld(Caster source) { - return dimension.map(source.asWorld().getServer()::getWorld); + return dimension.get().map(source.asWorld().getServer()::getWorld); } @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.put("spell", Spell.writeNbt(delegate)); - position.ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos))); - orientation.ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o))); - dimension.ifPresent(d -> compound.putString("dimension", d.getValue().toString())); - if (placedEntityId != null) { - compound.putUuid("placedEntityId", placedEntityId); + position.get().ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos))); + orientation.get().ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o))); + dimension.get().ifPresent(d -> compound.putString("dimension", d.getValue().toString())); + if (placedEntityId.get() != null) { + compound.putUuid("placedEntityId", placedEntityId.get()); } } @@ -139,12 +135,10 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel public void fromNBT(NbtCompound compound) { super.fromNBT(compound); delegate = Spell.readNbt(compound.getCompound("spell")); - placedEntityId = compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null; - position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.DOUBLE_TYPE))) : Optional.empty(); - orientation = compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.DOUBLE_TYPE))) : Optional.empty(); - if (compound.contains("dimension", NbtElement.STRING_TYPE)) { - dimension = Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)); - } + placedEntityId.set(compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null); + position.set(compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.DOUBLE_TYPE))) : Optional.empty()); + orientation.set(compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.DOUBLE_TYPE))) : Optional.empty()); + dimension.set(compound.contains("dimension", NbtElement.STRING_TYPE) ? Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)) : Optional.empty()); } public interface PlacementDelegate { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java index aab10703..6add4b0f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java @@ -74,18 +74,6 @@ public interface Spell extends NbtSerialisable, Affine { boolean isDying(); - /** - * Returns true if this effect has changes that need to be sent to the client. - */ - @Deprecated - boolean isDirty(); - - /** - * Marks this effect as dirty. - */ - @Deprecated - void setDirty(); - /** * Applies this spell to the supplied caster. * @param caster The caster to apply the spell to diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java index 4bab564c..66cd3acc 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java @@ -25,11 +25,6 @@ public final class SpellReference implements NbtSerialisable { set(spell, null); } - @Deprecated - public boolean hasDirtySpell() { - return spell != null && spell.isDirty(); - } - public boolean set(T spell, @Nullable Caster owner) { spell = spell == null || spell.isDead() ? null : spell; if (spell == this.spell) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java index 6d08d6a9..16839123 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java @@ -20,7 +20,6 @@ public abstract class AbstractSpell implements Spell { private final DataTracker.Entry dead = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private final DataTracker.Entry dying = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); - private boolean dirty; private final DataTracker.Entry hidden = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private boolean destroyed; @@ -66,18 +65,6 @@ public abstract class AbstractSpell implements Spell { return dying.get(); } - @Deprecated - @Override - public final boolean isDirty() { - return dirty; - } - - @Deprecated - @Override - public final void setDirty() { - dirty = true; - } - @Override public final boolean isHidden() { return hidden.get(); @@ -120,7 +107,6 @@ public abstract class AbstractSpell implements Spell { @Override public void fromNBT(NbtCompound compound) { - dirty = false; if (compound.containsUuid("uuid")) { uuid = compound.getUuid("uuid"); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java index 7bf39425..08b6e1a2 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java @@ -28,14 +28,12 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp static final TooltipFactory TARGET = (type, tooltip) -> (TARGET_FOCUSED_ENTITY.get(type.traits()) ? TARGET_FOCUSED_ENTITY : ShieldSpell.TARGET).appendTooltip(type, tooltip); static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, RANGE, TARGET, STICK_TO_TARGET, CAST_ON); - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); protected AttractiveSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); - dataTracker.startTracking(target); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java index dab51b1b..7a9402c5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java @@ -19,11 +19,10 @@ import net.minecraft.registry.Registries; public class AwkwardSpell extends AbstractSpell implements TimedSpell { - private final Timer timer; + private final Timer timer = new Timer(20); protected AwkwardSpell(CustomisedSpellType type) { super(type); - timer = new Timer(20); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java index df1e9c92..dfd6d601 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java @@ -56,17 +56,14 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell, static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); private float prevRadius; - private DataTracker.Entry radius; - private DataTracker.Entry struggles; + private DataTracker.Entry radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); + private DataTracker.Entry struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits())); protected BubbleSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); - radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); - struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java index e90558d0..8f7ffabf 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java @@ -59,11 +59,10 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell { .with(Trait.ORDER, 15) .build(); - private final Timer timer; + private final Timer timer = new Timer(DURATION.get(getTraits())); protected FeatherFallSpell(CustomisedSpellType type) { super(type); - timer = new Timer(DURATION.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java index 9075457a..04cf61fd 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java @@ -47,7 +47,7 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, static final TooltipFactory TOOLTIP = TooltipFactory.of(EXPLOSION_STRENGTH, VELOCITY, PROJECTILE_COUNT, FOLLOWS_TARGET, FOLLOW_RANGE.conditionally(FOLLOWS_TARGET::get)); - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); protected FireBoltSpell(CustomisedSpellType type) { super(type); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java index 2c14e4f8..d1bf985f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java @@ -38,13 +38,12 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, ORB_COUNT); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); private final List> lights = new ArrayList<>(); protected LightSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java index 57b984c1..1108bd43 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java @@ -11,11 +11,10 @@ public class MimicSpell extends AbstractDisguiseSpell implements HomingSpell, Ti static final TooltipFactory TOOLTIP = TimedSpell.TIME; - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); protected MimicSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index 4277ff0c..bb007fe5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -46,7 +46,7 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. private final DataTracker.Entry targetPortalId = dataTracker.startTracking(TrackableDataType.UUID, Util.NIL_UUID); private final DataTracker.Entry targetPortalPitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); private final DataTracker.Entry targetPortalYaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); - private final EntityReference teleportationTarget = new EntityReference<>(); + private final EntityReference teleportationTarget = dataTracker.startTracking(new EntityReference<>()); private final DataTracker.Entry pitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); private final DataTracker.Entry yaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java index 8b759a18..0e1dcd76 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java @@ -67,10 +67,6 @@ class EntityReplacementManager implements Disguise { return disguise; } - @Override - public void setDirty() { - } - @Override public boolean isDead() { return false; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index b34606f7..9604dfc1 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -24,8 +24,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider EntityAppearance getDisguise(); - void setDirty(); - boolean isDead(); default Optional getAppearance() { @@ -57,7 +55,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider } getDisguise().setAppearance(entity); - setDirty(); return this; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java index acba1d32..f2c0c56f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java @@ -21,6 +21,7 @@ import com.minelittlepony.unicopia.entity.mob.SombraEntity; import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; import com.minelittlepony.unicopia.entity.player.PlayerDimensions; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.network.track.TrackableObject; import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.mojang.authlib.GameProfile; @@ -51,7 +52,7 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; -public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider, EntityCollisions.ComplexCollidable { +public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider, EntityCollisions.ComplexCollidable, TrackableObject { private static final Optional BLOCK_HEIGHT = Optional.of(0.5F); @NotNull @@ -77,6 +78,8 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi @Nullable private NbtCompound entityNbt; + private boolean dirty; + @Nullable public Entity getAppearance() { return entity; @@ -109,6 +112,7 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi entityNbt = entity == null ? null : encodeEntityToNBT(entity); entityId = entityNbt == null ? "" : entityNbt.getString("id"); + markDirty(); } public boolean isPresent() { @@ -393,4 +397,44 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi getAttachments().forEach(e -> EntityCollisions.getCollissionShapes(e.entity(), context, output)); } + public void markDirty() { + dirty = true; + } + + @Override + public Status getStatus() { + if (dirty) { + dirty = false; + return Status.UPDATED; + } + return Status.DEFAULT; + } + + @Override + public void readTrackedNbt(NbtCompound nbt) { + fromNBT(nbt); + } + + @Override + public NbtCompound writeTrackedNbt() { + return toNBT(); + } + + @Override + public void discard(boolean immediate) { + setAppearance(null); + dirty = false; + } + + @Override + public void copyTo(EntityAppearance destination) { + destination.entityId = entityId; + destination.entity = entity; + destination.blockEntity = blockEntity; + destination.attachments.addAll(attachments); + destination.dimensions = dimensions; + destination.tag = tag == null ? null : tag.copy(); + destination.entityNbt = entityNbt == null ? null : entityNbt.copy(); + } + } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java index c4074e27..1a7ac949 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java @@ -65,7 +65,7 @@ public class SheepBehaviour extends EntityBehaviour { } } while (dropAmount-- > 0); } - spell.setDirty(); + spell.getAppearance().ifPresent(EntityAppearance::markDirty); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java index 9c5c6b74..e918e3e7 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java @@ -11,8 +11,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; public record TrackableDataType(int id, PacketCodec codec) { private static final Int2ObjectMap> REGISTRY = new Int2ObjectOpenHashMap<>(); @@ -26,8 +28,16 @@ public record TrackableDataType(int id, PacketCodec codec) { public static final TrackableDataType> RAW_BYTES = of(new Identifier("raw_bytes"), PacketCodec.RAW_BYTES.asOptional()); public static final TrackableDataType> OPTIONAL_POS = of(new Identifier("optional_pos"), PacketCodec.OPTIONAL_POS); + public static final TrackableDataType> OPTIONAL_VECTOR = of(new Identifier("optional_vector"), PacketCodec.OPTIONAL_VECTOR); + private static final TrackableDataType>> OPTIONAL_REGISTRY_KEY = of(new Identifier("optional_registry_key"), PacketCodec.OPTIONAL_REGISTRY_KEY); + public static final TrackableDataType RACE = TrackableDataType.of(Unicopia.id("race"), PacketCodec.ofRegistry(Race.REGISTRY)); + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static TrackableDataType>> ofRegistryKey() { + return (TrackableDataType)OPTIONAL_REGISTRY_KEY; + } + @SuppressWarnings("unchecked") public static TrackableDataType of(PacketByteBuf buffer) { int id = buffer.readInt(); diff --git a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java index 03336ec2..cd964b76 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java +++ b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java @@ -16,9 +16,11 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf.PacketWriter writer) { public static final PacketCodec BOOLEAN = new PacketCodec<>(PacketByteBuf::readBoolean, PacketByteBuf::writeBoolean); @@ -30,7 +32,7 @@ public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf public static final PacketCodec UUID = new PacketCodec<>(PacketByteBuf::readUuid, PacketByteBuf::writeUuid); public static final PacketCodec> OPTIONAL_UUID = UUID.asOptional(); - public static final PacketCodec IDENTIFIER = STRING.xMap(Identifier::new, Identifier::toString); + public static final PacketCodec IDENTIFIER = new PacketCodec<>(PacketByteBuf::readIdentifier, PacketByteBuf::writeIdentifier); public static final PacketCodec NBT = new PacketCodec<>(PacketByteBuf::readNbt, PacketByteBuf::writeNbt); @@ -58,6 +60,19 @@ public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf public static final PacketCodec POS = new PacketCodec<>(PacketByteBuf::readBlockPos, PacketByteBuf::writeBlockPos); public static final PacketCodec> OPTIONAL_POS = POS.asOptional(); + public static final PacketCodec VECTOR = new PacketCodec<>(buffer -> new Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()), (buffer, vector) -> { + buffer.writeDouble(vector.x); + buffer.writeDouble(vector.y); + buffer.writeDouble(vector.z); + }); + public static final PacketCodec> OPTIONAL_VECTOR = VECTOR.asOptional(); + public static final PacketCodec> REGISTRY_KEY = new PacketCodec<>(buffer -> { + return RegistryKey.of(RegistryKey.ofRegistry(IDENTIFIER.read(buffer)), IDENTIFIER.read(buffer)); + }, (buffer, key) -> { + IDENTIFIER.write(buffer, key.getRegistry()); + IDENTIFIER.write(buffer, key.getValue()); + }); + public static final PacketCodec>> OPTIONAL_REGISTRY_KEY = REGISTRY_KEY.asOptional(); public static final PacketCodec ofRegistry(Registry registry) { return INT.xMap(registry::get, registry::getRawId); From e8649aca7de8c19e07766a51bbb8d6be3aec0129 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:40:40 +0100 Subject: [PATCH 34/81] Remove redundant effect nbt field --- .../java/com/minelittlepony/unicopia/entity/Creature.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java index c319f104..4be62edd 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java @@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.WeaklyOwned; import com.minelittlepony.unicopia.ability.magic.*; -import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.TargetSelecter; import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal; import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal; @@ -302,9 +301,6 @@ public class Creature extends Living implements WeaklyOwned.Mutabl @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); - getSpellSlot().get().ifPresent(effect -> { - compound.put("effect", Spell.writeNbt(effect)); - }); compound.put("master", getMasterReference().toNBT()); physics.toNBT(compound); compound.putBoolean("discorded", isDiscorded()); @@ -313,9 +309,6 @@ public class Creature extends Living implements WeaklyOwned.Mutabl @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); - if (compound.contains("effect")) { - getSpellSlot().put(Spell.readNbt(compound.getCompound("effect"))); - } if (compound.contains("master", NbtElement.COMPOUND_TYPE)) { owner.fromNBT(compound.getCompound("master")); if (owner.isSet()) { From 89124eb146dbe0d702ddc78adecd3757b90c74c9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:41:04 +0100 Subject: [PATCH 35/81] Fixed disguises applied via commands not remaining when applied to a non-changeling entity --- .../ability/magic/spell/DispersableDisguiseSpell.java | 11 ++++++++++- .../unicopia/command/DisguiseCommand.java | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java index 7f614bc6..2b7f7cb8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java @@ -26,11 +26,18 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I private final DataTracker.Entry suppressed = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private int suppressionCounter; + private boolean forced; + public DispersableDisguiseSpell(CustomisedSpellType type) { super(type); setHidden(true); } + public void setForced() { + forced = true; + setHidden(false); + } + @Override public boolean isVulnerable(Caster otherSource, Spell other) { return suppressionCounter <= otherSource.getLevel().get(); @@ -59,7 +66,7 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I } } - if (!source.canUse(Abilities.DISGUISE)) { + if (!forced && !source.canUse(Abilities.DISGUISE)) { setDead(); } @@ -91,12 +98,14 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.putInt("suppressionCounter", suppressionCounter); + compound.putBoolean("forced", forced); } @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); suppressionCounter = compound.getInt("suppressionCounter"); + forced = compound.getBoolean("forced"); if (suppressionCounter > 0) { suppressed.set(true); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java index d735c89a..5dba2c32 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java @@ -4,8 +4,10 @@ import java.util.function.Function; import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.InteractionManager; +import com.minelittlepony.unicopia.ability.Abilities; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; +import com.minelittlepony.unicopia.ability.magic.spell.DispersableDisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.mojang.authlib.GameProfile; @@ -81,7 +83,13 @@ public class DisguiseCommand { Pony iplayer = Pony.of(player); iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE) - .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE)) + .orElseGet(() -> { + DispersableDisguiseSpell spell = SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE); + if (!iplayer.canUse(Abilities.DISGUISE)) { + spell.setForced(); + } + return spell; + }) .setDisguise(entity); if (source.getEntity() == player) { From c75b4b36b8a278a11f482d3f37d4c133427455a4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:41:21 +0100 Subject: [PATCH 36/81] Update iris dependency --- build.gradle | 7 ++++++- gradle.properties | 1 + .../unicopia/client/gui/DismissSpellScreen.java | 5 ----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index de730eec..4682312e 100644 --- a/build.gradle +++ b/build.gradle @@ -102,7 +102,12 @@ dependencies { if (project.use_sodium == '1') { modCompileOnly "maven.modrinth:indium:${project.indium_version}", { exclude group: "net.fabricmc.fabric-api" } modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" } - // modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + if (project.use_iris == '1') { + modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + modImplementation "org.anarres:jcpp:1.4.14" + modImplementation "org.antlr:antlr4-runtime:4.13.1" + modImplementation "io.github.douira:glsl-transformer:2.0.1" + } } if (project.tmi_type == 'emi') { diff --git a/gradle.properties b/gradle.properties index 25ccc1c3..a11af593 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,6 +33,7 @@ org.gradle.daemon=false use_trinkets=1 use_pehkui=0 use_sodium=1 + use_iris=1 farmers_delight_version=1.20.1-2.0.9 pehkui_version=3.7.8+1.14.4-1.20.1 diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index 23b90dc6..cddf13b9 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,11 +101,6 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } - @Override - public void renderInGameBackground(DrawContext context) { - - } - @Override public boolean shouldPause() { return false; From 5b443f118d72fa8453d20b572af30b76013a6e48 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 22:46:18 +0100 Subject: [PATCH 37/81] Adjust changeling hive size --- .../worldgen/structure/abandoned_changeling_hive.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json index 70b16c5a..452e16aa 100644 --- a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json +++ b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json @@ -3,7 +3,7 @@ "biomes": "#minecraft:is_forest", "max_distance_from_center": 112, "project_start_to_heightmap": "WORLD_SURFACE_WG", - "size": 7, + "size": 20, "spawn_overrides": { "monster": { "bounding_box": "piece", @@ -21,7 +21,7 @@ "absolute": -7 }, "start_pool": "unicopia:changeling_hive/start", - "step": "underground_decoration", + "step": "underground_structures", "terrain_adaptation": "none", "use_expansion_hack": false } \ No newline at end of file From f8018cb6fc54e25f566d0e76c3a842da7374f5f5 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 14:48:34 +0100 Subject: [PATCH 38/81] Improve changeling hive generation. Fixes #398 --- .../unicopia/server/world/UWorldGen.java | 6 ++ .../gen/CaveCarvingStructureProcessor.java | 36 ++++++++++ .../gen/SurfaceGrowthStructureProcessor.java | 67 ++++++++++++++++++ .../changeling_hive/entrance_large_lower.nbt | Bin 0 -> 4916 bytes .../changeling_hive/entrance_large_upper.nbt | Bin 0 -> 4511 bytes .../floor_decoration/empty.nbt | Bin 0 -> 282 bytes .../floor_decoration/slime_1.nbt | Bin 0 -> 327 bytes .../floor_decoration/slime_2.nbt | Bin 0 -> 329 bytes .../floor_decoration/slime_3.nbt | Bin 0 -> 327 bytes .../floor_decoration/spikes.nbt | Bin 0 -> 313 bytes .../changeling_hive/roof_decoration/empty.nbt | Bin 0 -> 271 bytes .../changeling_hive/roof_decoration/slime.nbt | Bin 0 -> 327 bytes .../roof_decoration/spikes.nbt | Bin 0 -> 303 bytes .../processor_list/changeling_hive_decay.json | 17 ++++- .../changeling_hive_entrance_decay.json | 32 +++++++++ .../changeling_hive_surfacing.json | 13 ++++ .../structure/abandoned_changeling_hive.json | 2 +- .../changeling_hive/chamber_decors.json | 16 ++--- .../changeling_hive/floor_additions.json | 50 +++++++++++++ .../floor_additions_termination.json | 14 ++++ .../changeling_hive/main_entrance_shafts.json | 14 ++++ .../changeling_hive/pit_decors.json | 20 ++---- .../changeling_hive/roof_additions.json | 32 +++++++++ .../roof_additions_termination.json | 14 ++++ .../template_pool/changeling_hive/start.json | 22 +----- 25 files changed, 305 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_upper.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/empty.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt create mode 100644 src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_entrance_decay.json create mode 100644 src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_surfacing.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions_termination.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/main_entrance_shafts.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions_termination.json diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java index c7c781a6..5100d075 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java @@ -6,7 +6,9 @@ import java.util.function.Consumer; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.ShellsBlock; import com.minelittlepony.unicopia.block.UBlocks; +import com.minelittlepony.unicopia.server.world.gen.CaveCarvingStructureProcessor; import com.minelittlepony.unicopia.server.world.gen.OverworldBiomeSelectionCallback; +import com.minelittlepony.unicopia.server.world.gen.SurfaceGrowthStructureProcessor; import com.minelittlepony.unicopia.util.registry.DynamicRegistry; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; @@ -23,6 +25,7 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.BiomeTags; import net.minecraft.sound.BiomeMoodSound; import net.minecraft.sound.SoundEvents; +import net.minecraft.structure.processor.StructureProcessorType; import net.minecraft.util.collection.DataPool; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; @@ -120,6 +123,9 @@ public interface UWorldGen { .build(); }); + StructureProcessorType SURFACE_GROWTH_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("surface_growth"), () -> SurfaceGrowthStructureProcessor.CODEC); + StructureProcessorType CAVE_CARVING_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("cave_carving"), () -> CaveCarvingStructureProcessor.CODEC); + @SafeVarargs static T applyAll(T t, Consumer ...consumers) { for (Consumer consumer : consumers) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java new file mode 100644 index 00000000..cfb2db26 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java @@ -0,0 +1,36 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.server.world.UWorldGen; +import com.mojang.serialization.Codec; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.structure.processor.StructureProcessor; +import net.minecraft.structure.processor.StructureProcessorType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Heightmap; +import net.minecraft.world.WorldView; + +public class CaveCarvingStructureProcessor extends StructureProcessor { + public static final Codec CODEC = Codec.unit(new CaveCarvingStructureProcessor()); + + @Override + protected StructureProcessorType getType() { + return UWorldGen.SURFACE_GROWTH_STRUCTURE_PROCESSOR; + } + + @Nullable + @Override + public StructureTemplate.StructureBlockInfo process( + WorldView world, + BlockPos pos, + BlockPos pivot, + StructureTemplate.StructureBlockInfo originalBlockInfo, + StructureTemplate.StructureBlockInfo currentBlockInfo, + StructurePlacementData data + ) { + int topY = world.getTopY(Heightmap.Type.WORLD_SURFACE_WG, currentBlockInfo.pos().getX(), currentBlockInfo.pos().getZ()); + return currentBlockInfo.pos().getY() > topY && world.isAir(currentBlockInfo.pos()) ? null : currentBlockInfo; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java new file mode 100644 index 00000000..33ef60c7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java @@ -0,0 +1,67 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.minelittlepony.unicopia.server.world.UWorldGen; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.block.BlockState; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.structure.processor.StructureProcessor; +import net.minecraft.structure.processor.StructureProcessorType; +import net.minecraft.structure.rule.RuleTest; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.ServerWorldAccess; + +public class SurfaceGrowthStructureProcessor extends StructureProcessor { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + RuleTest.TYPE_CODEC.fieldOf("input_predicate").forGetter(rule -> rule.inputPredicate), + BlockState.CODEC.fieldOf("output_state").forGetter(rule -> rule.outputState) + ).apply(instance, SurfaceGrowthStructureProcessor::new)); + + private final RuleTest inputPredicate; + private final BlockState outputState; + + public SurfaceGrowthStructureProcessor(RuleTest inputPredicate, BlockState outputState) { + this.inputPredicate = inputPredicate; + this.outputState = outputState; + } + + @Override + protected StructureProcessorType getType() { + return UWorldGen.SURFACE_GROWTH_STRUCTURE_PROCESSOR; + } + + @SuppressWarnings("deprecation") + @Override + public List reprocess( + ServerWorldAccess world, + BlockPos pos, + BlockPos pivot, + List originalBlockInfos, + List currentBlockInfos, + StructurePlacementData data + ) { + Map positionalInfos = currentBlockInfos.stream().collect(Collectors.toMap( + StructureTemplate.StructureBlockInfo::pos, + Function.identity() + )); + + return currentBlockInfos.stream().map(currentBlockInfo -> { + StructureTemplate.StructureBlockInfo aboveBlockInfo = positionalInfos.get(currentBlockInfo.pos().up()); + BlockState currentState = aboveBlockInfo == null ? world.getBlockState(currentBlockInfo.pos().up()) : aboveBlockInfo.state(); + if ((currentState.isAir() || currentState.isReplaceable()) + && inputPredicate.test(currentBlockInfo.state(), Random.create(MathHelper.hashCode(currentBlockInfo.pos())))) { + return new StructureTemplate.StructureBlockInfo(currentBlockInfo.pos(), outputState, currentBlockInfo.nbt()); + } + return currentBlockInfo; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt new file mode 100644 index 0000000000000000000000000000000000000000..2a6cd5e5994ef45fe5dd4ab84793728f0e7166c4 GIT binary patch literal 4916 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt new file mode 100644 index 0000000000000000000000000000000000000000..86e553a77752d5174b62baff89541c6e09856ef5 GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|BX;hPs1<__11N?odjqXega3tb!X0q6W7X1-7F(bqQqqy zzaD3UO>7q;S&hFLOSQ~*G(iPSXTHB{u-u%QI`)G%LLuRcq%~Zw6O)ny9@TYz=h_`5KJB?O ZEm{{Z$oNh%WenUhd;>5yS9Uf6008VtkM{ro literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt new file mode 100644 index 0000000000000000000000000000000000000000..185d053bcaa849240b629405dc0ef9cc9b260772 GIT binary patch literal 329 zcmV-P0k-}hiwFP!00000|BX;hPs1<__10~)odjqXega1%jyrQkoVZqA>ZTcK93?5! z`1Lp&Y+}0*$%>r#`F+#?70jafq5=SNO{AvzuAn5BOfnQ9p9&Tm%jzT6d7^^CbNmIt z4^WzUOql5KQbXZ3sf78KjZ07lwiY**N|-qu2p&gg6nlef)uYp7jnhqUKIy5m%%Q=y z6?%3u@0l&!4aSiQ*rhcMKJ80bcE+J?j+76lb#V+GDr!_Ocvry6TWJTe)A(RGn6y8N zT}85_GRL2f5~ikw`!n6v=!m-#772r<^l#;G9TQx{G?AGbkCsxRL$Wp0Z-G69oV-}v z$y~6kHMKDB&_>B`u6UG0C(j~v_L{Rin;-U30EWldkk)XyPE1M;cu-fjymL+DG4-cK bSFT0u@&yyVQ-~P^w+X%hp_V2{Hv#|v<29Gh literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..53574e14b0c8f8321f46475426f3f1fea79b46e1 GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|BX;RPs1<}y*5orQVCEOegY!{TW4m(#2Q_li|gXpmVKcr zzn*got!Ni4ovgF(-TP<&YM3SSMFjxlnn+FaT|-5V4I4_3PYv_6_39%vd7_3Q`1A{c zAD}d4Vq`kJG*GxTS5R)faST=T*5cYy1v7^O!Q<$R^1@{b3Hb3l>0E{0~OIpL_Ix#6Z;89)Ycdp%0;?tfh Z)1r0pf{gDJQ^vq8!#Av(Q=>Kl007qdn^^z= literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt new file mode 100644 index 0000000000000000000000000000000000000000..c3932214c36bf1478af26bef2737f593157af818 GIT binary patch literal 313 zcmV-90ml9xiwFP!00000|BX>iPXaLz9azBKB~imce}YHvoIM*)UYlWeb{XilO*=^N z*E+1tmFQVM>r!1+$g)%{JA!qkQiHVY>0`1j^{G#g(NJCJqOJhn?fb2gYTyM%R;N*PAuJ(PL-5j|SUT z>Alnb;Jt;LfgLpwJ6X~Yf{Ik>wY^x2_Ffw%fi7tpyHQqOo&()ztKdrER1^T(j-nm?i7E5(#Ca4qlw L4FAa=A_4#aTq%?h literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt new file mode 100644 index 0000000000000000000000000000000000000000..bd44b266639761e1f44abb40d6834671cbebd6c2 GIT binary patch literal 271 zcmV+q0r37GiwFP!00000|BaB#P6IIvMK4Sr=~SYqAHkM=*Q^mMwj|_OF4#t*mkX{moALL`Q>(QtVm( z3!F7n!KbUOuc|P16fw(PgnIz^nqh>nJ>#wnVZgW(?e*EoU%cTo{P9Yh&g)x VL`tt5Q`x|s;sYzGLBF>F002Eig!cdd literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt new file mode 100644 index 0000000000000000000000000000000000000000..521802b8222631121cec0b2a68a8e0dd04e2905d GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|CNzJQ^GJ1g%?U8Ei>Y9@F#fn&e^l$$!lk6w`DO+GRam3 zf4vC^Dtf@oWOCTIZ{L0?0ScG|ey0oo(jA@N0u&ixVG58=0n@d%^=l}TqJYfVaB4cA z4Dui-^x1K#8C_^bP(o(bq9ET|HUi39t#PeM!Ng!sa6cHXtz%r(8#EnhHeI#hH+t~a zwiPx_OlVD%J8Ly8dNx#hY-L5glf8m@%La9IoVfVr7W+&FOQ*4>K5kk$&(^c-j~SPN zG}X!bM?t}u8@T-%v*j+}PQg^rcO=&a{sYeV0?s&UW)3xp(1Cdg<+HbreEJg=Yj#JT z8pvDJAri~O1|22eCgz+xC4P73I6-qyl^cQ#n&4Wm8r^@r<`GupiH9|3gR2OGoK1eA Zi!09`QSgO)NF8t^@BxT&kzkhs0045jlU4u# literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt new file mode 100644 index 0000000000000000000000000000000000000000..7a388fabc20f4bec549d75eba9bcd8dab663ccbc GIT binary patch literal 303 zcmV+~0nq**iwFP!00000|BX@2Zo)7OHnc!mq%m>e5q903^Ul*wyH+N3iy=*-#0;^g zUjiE2;4({A6vh7jQUg>_M*gG%0CJB~kMmi9A}cIR5pq>9-596$vCb0}6yC+}rE3*1 ziGo7sOAUqHh=R$^u@z9k8G{=`3QCIu!PCLAcAjyqw`hAZZ2M-*AM_lY>l$p^#O`bw z_s$tu3~WgU>|{-Ymy?2d#}-XEa39X-CY({4nRzrMLgzedsNaI~6ms5)u|u7}p={mJCSm1k z4s3N}v5B7d>3eRL=gCnrjb|;hgKv%$ Date: Tue, 24 Sep 2024 15:00:42 +0100 Subject: [PATCH 39/81] Fixed non-pegasi not able to jump out of cloud blocks --- .../com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index fd526300..05953dc8 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -105,10 +105,9 @@ public class CloudBlock extends Block implements CloudLike { entity.addVelocity(0, 0.07, 0); entity.setOnGround(true); } - entity.setVelocity(entity.getVelocity().multiply(0.9F, 1, 0.9F)); - } else { - entity.setVelocity(entity.getVelocity().multiply(0.9F)); } + + entity.setVelocity(entity.getVelocity().multiply(0.9F, 1, 0.9F)); } @Override From 1ff0e89724212f06229a387f3ba9f4353c72e9c9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:01:13 +0100 Subject: [PATCH 40/81] Creative players can now interact with cloud blocks regardless of tribe. Closes #461 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 5 +++++ 1 file changed, 5 insertions(+) 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 cba9e735..ca4aa870 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -224,6 +224,11 @@ public class Pony extends Living implements Copyable, Update return compositeRace; } + @Override + public boolean collidesWithClouds() { + return getCompositeRace().canInteractWithClouds() || entity.isCreative(); + } + @Override public void setSpecies(Race race) { race = race.validate(entity); From 797e2101b529a5861e3494190888c815f176937c Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:16:18 +0100 Subject: [PATCH 41/81] Fix layering on the tribe confirmation screen --- .../client/gui/TribeConfirmationScreen.java | 18 +++++------------- .../structure/abandoned_changeling_hive.json | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java index a4a82e64..27fe88d7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java @@ -104,10 +104,12 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { + context.getMatrices().push(); + context.getMatrices().translate(0, 0, -2); if (parent != null) { context.getMatrices().push(); context.getMatrices().translate(0, 0, -100); - parent.render(context, 0, 0, delta); + parent.render(context, -1, -1, delta); context.getMatrices().pop(); } renderBackground(context); @@ -120,30 +122,20 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { int left = (width - columnWidth) / 2; top += 40; - final int zOffset = 0; context.drawTexture(TribeSelectionScreen.TEXTURE, left + zOffset, top, 0, 70, 123, columnHeight); - context.drawTexture(TribeSelectionScreen.TEXTURE, left + segmentWidth + zOffset, top, 20, 70, 123, columnHeight); - - context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset, top, 10, 70, 123, columnHeight); - + context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset + 1, top, 10, 70, 123, columnHeight); top -= 31; - left = width / 2; - context.drawTexture(TribeSelectionScreen.TEXTURE, left - 55, top, 140, 70, 21, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50); - textBody.render(context, mouseX, mouseY, delta); - - context.getMatrices().push(); - context.getMatrices().translate(0, 0, 2); + context.getMatrices().pop(); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50); super.render(context, mouseX, mouseY, delta); - context.getMatrices().pop(); } @Override diff --git a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json index 978a4940..d88b505b 100644 --- a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json +++ b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json @@ -3,7 +3,7 @@ "biomes": "#minecraft:is_forest", "max_distance_from_center": 112, "project_start_to_heightmap": "WORLD_SURFACE_WG", - "size": 20, + "size": 7, "spawn_overrides": { "monster": { "bounding_box": "piece", From 95da98b8c3024db49fae2d19604d006250441bcf Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:16:49 +0100 Subject: [PATCH 42/81] Fix #466 --- src/main/java/com/minelittlepony/unicopia/Race.java | 2 +- src/main/resources/assets/unicopia/lang/en_us.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index 84994481..8607c091 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -70,7 +70,7 @@ public record Race ( * This is used if there are no other races. */ public static final Race UNSET = register("unset", new Builder().availability(Availability.COMMANDS)); - public static final Race HUMAN = register("human", new Builder().availability(Availability.COMMANDS)); + public static final Race HUMAN = register("human", new Builder()); public static final Race EARTH = register("earth", new Builder().foraging().earth() .abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW) ); diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 3d8903f2..6005597f 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -799,6 +799,7 @@ "gui.unicopia.tribe_selection.options": "Available Tribes:", "gui.unicopia.tribe_selection.options.disabled": "Option Unavailable", + "gui.unicopia.tribe_selection.describe.unicopia.human": "Got it alone", "gui.unicopia.tribe_selection.describe.unicopia.earth": "Join the Earth Tribe", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "Join the Unicorn Tribe, master the arcane arts", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "Join the Pegasus Tribe, soar with the Wonderbolts", From bee81cae748eefde33eecc1af4dfb1dad25aeacb Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:45:26 +0100 Subject: [PATCH 43/81] Make gemstones edible for earth ponies. Fixes #460 --- .../java/com/minelittlepony/unicopia/UConventionalTags.java | 1 + .../unicopia/datagen/providers/DietProfileGenerator.java | 2 ++ .../unicopia/datagen/providers/FoodGroupsGenerator.java | 1 + .../unicopia/datagen/providers/tag/UItemTagProvider.java | 1 + 4 files changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java b/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java index 6b54e607..31b02f7f 100644 --- a/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java +++ b/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java @@ -46,6 +46,7 @@ public interface UConventionalTags { TagKey FRUITS = item("fruits"); TagKey WORMS = item("worms"); TagKey ROCKS = item("rocks"); + TagKey GEMS = item("gems"); TagKey RAW_INSECT = item("raw_insect"); TagKey COOKED_INSECT = item("cooked_insect"); diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java index 4034021f..cfa28601 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java @@ -148,12 +148,14 @@ public class DietProfileGenerator { bakedGoodExtremePreference, pineconeMultiplier, properMeatStandards, seaFoodExclusions, // They have a sweet tooth new Multiplier.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("desserts")).tag(Unicopia.id("rocks")).hunger(2.5F).saturation(1.7F).build(), + new Multiplier.Builder().tag(Unicopia.id("gems")).hunger(0.5F).saturation(0.7F).build(), new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.2F).saturation(0.3F).build(), new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.1F).build(), new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.1F).saturation(0.1F).build() ), List.of( // Candy and rocks gives them a massive saturation boost. Maybe too much? new FoodGroupEffects.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("rocks")).food(UFoodComponents.builder(5, 12).alwaysEdible()).build(), + new FoodGroupEffects.Builder().tag(Unicopia.id("gems")).food(UFoodComponents.builder(2, 1.5F).snack().alwaysEdible()).build(), new FoodGroupEffects.Builder().tag(Unicopia.id("desserts")).food(UFoodComponents.builder(12, 32).snack().alwaysEdible()).build() ), Optional.empty())); // Pegasi prefer fish over other food sources diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java index a30de498..47864d46 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java @@ -31,6 +31,7 @@ public class FoodGroupsGenerator { exporter.accept(Unicopia.id("desserts"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.DESSERTS).food(FoodComponents.COOKIE)); exporter.accept(Unicopia.id("fruit"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.FRUITS).food(UFoodComponents.BANANA)); exporter.accept(Unicopia.id("rocks"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.ROCKS).tag(UTags.Items.ROCK_STEWS).food(FoodComponents.MUSHROOM_STEW)); + exporter.accept(Unicopia.id("gems"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.GEMS)); exporter.accept(Unicopia.id("shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SHELLS).food(UFoodComponents.SHELL)); exporter.accept(Unicopia.id("special_shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SPECIAL_SHELLS).food(UFoodComponents.SHELLY)); exporter.accept(Unicopia.id("love"), new FoodGroupEffects.Builder().tag(UTags.Items.CONTAINER_WITH_LOVE).food(UFoodComponents.LOVE_MUG).ailment(new CompoundAffliction(List.of( diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java index 9e579480..ec4dd783 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java @@ -353,6 +353,7 @@ public class UItemTagProvider extends FabricTagProvider.ItemTagProvider { getOrCreateTagBuilder(UConventionalTags.Items.WORMS).add(UItems.WHEAT_WORMS); getOrCreateTagBuilder(UConventionalTags.Items.STICKS).add(Items.STICK); getOrCreateTagBuilder(UConventionalTags.Items.ROCKS).add(UItems.ROCK); + getOrCreateTagBuilder(UConventionalTags.Items.GEMS).add(UItems.GEMSTONE, UItems.BOTCHED_GEM); getOrCreateTagBuilder(UConventionalTags.Items.PINECONES).add(UItems.PINECONE); getOrCreateTagBuilder(UConventionalTags.Items.PINEAPPLES).add(UItems.PINEAPPLE); getOrCreateTagBuilder(UConventionalTags.Items.MANGOES).add(UItems.MANGO); From 36a8a9d018709e4a09fff6b969416cbf3471a2b6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:45:49 +0100 Subject: [PATCH 44/81] Reduce hunger granted by eating placed hay bales --- .../java/com/minelittlepony/unicopia/block/EdibleBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java b/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java index e6bf0482..707853b1 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java @@ -205,7 +205,7 @@ public class EdibleBlock extends HayBlock { if (world.random.nextInt(10) == 0) { player.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, player.getSoundPitch()); } - player.getHungerManager().add(4, 2.3F); + player.getHungerManager().add(2, 1.3F); } return ActionResult.SUCCESS; } From c7a0c7b527bb4c860a81af81b577c11689b220b1 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:52:19 +0100 Subject: [PATCH 45/81] Reduce chance of mobs reproducing when they have the corrupt influence effect. Fixes #467 --- src/main/java/com/minelittlepony/unicopia/entity/Living.java | 2 +- .../unicopia/entity/effect/CorruptInfluenceStatusEffect.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 756a4491..e109876a 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -381,7 +381,7 @@ public abstract class Living implements Equine, Caste } } - if (entity instanceof HostileEntity mob && mob.hasStatusEffect(UEffects.CORRUPT_INFLUENCE) && mob.getRandom().nextInt(4) == 0) { + if (entity instanceof HostileEntity mob && mob.hasStatusEffect(UEffects.CORRUPT_INFLUENCE) && mob.getRandom().nextInt(4000) == 0) { CorruptInfluenceStatusEffect.reproduce(mob); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java index bf98ef9d..a30d7656 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java @@ -89,6 +89,9 @@ public class CorruptInfluenceStatusEffect extends StatusEffect { } } + if (mob.getRandom().nextInt(4) != 0) { + clone.clearStatusEffects(); + } mob.getWorld().spawnEntity(clone); if (!mob.isSilent()) { From c7c8e0971b45bf621cceff1763e76026815b87f3 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 18:34:58 +0100 Subject: [PATCH 46/81] Adjust polearm strengths --- .../com/minelittlepony/unicopia/item/UItems.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index c1f8081e..083e4ef8 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -146,12 +146,12 @@ public interface UItems { Item COPPER_HORSE_SHOE = register("copper_horse_shoe", new HorseShoeItem(new Item.Settings().maxDamage(250), 6, 0.5F, 0.8F), ItemGroups.COMBAT); Item NETHERITE_HORSE_SHOE = register("netherite_horse_shoe", new HorseShoeItem(new Item.Settings().maxDamage(800), 3, 0.7F, 1.2F), ItemGroups.COMBAT); - Item WOODEN_POLEARM = register("wooden_polearm", new PolearmItem(ToolMaterials.WOOD, 2, -3.6F, 2, new Item.Settings()), ItemGroups.COMBAT); - Item STONE_POLEARM = register("stone_polearm", new PolearmItem(ToolMaterials.STONE, 2, -3.6F, 2, new Item.Settings()), ItemGroups.COMBAT); - Item IRON_POLEARM = register("iron_polearm", new PolearmItem(ToolMaterials.IRON, 2, -3.6F, 3, new Item.Settings()), ItemGroups.COMBAT); - Item GOLDEN_POLEARM = register("golden_polearm", new PolearmItem(ToolMaterials.GOLD, 2, -3.6F, 4, new Item.Settings()), ItemGroups.COMBAT); - Item DIAMOND_POLEARM = register("diamond_polearm", new PolearmItem(ToolMaterials.DIAMOND, 2, -3.6F, 5, new Item.Settings()), ItemGroups.COMBAT); - Item NETHERITE_POLEARM = register("netherite_polearm", new PolearmItem(ToolMaterials.NETHERITE, 2, -3.6F, 5, new Item.Settings().fireproof()), ItemGroups.COMBAT); + Item WOODEN_POLEARM = register("wooden_polearm", new PolearmItem(ToolMaterials.WOOD, 2, -3.2F, 2, new Item.Settings()), ItemGroups.COMBAT); + Item STONE_POLEARM = register("stone_polearm", new PolearmItem(ToolMaterials.STONE, 2, -3.2F, 2, new Item.Settings()), ItemGroups.COMBAT); + Item IRON_POLEARM = register("iron_polearm", new PolearmItem(ToolMaterials.IRON, 2, -3.1F, 3, new Item.Settings()), ItemGroups.COMBAT); + Item GOLDEN_POLEARM = register("golden_polearm", new PolearmItem(ToolMaterials.GOLD, 3, -3F, 4, new Item.Settings()), ItemGroups.COMBAT); + Item DIAMOND_POLEARM = register("diamond_polearm", new PolearmItem(ToolMaterials.DIAMOND, 3, -3F, 5, new Item.Settings()), ItemGroups.COMBAT); + Item NETHERITE_POLEARM = register("netherite_polearm", new PolearmItem(ToolMaterials.NETHERITE, 3, -3F, 6, new Item.Settings().fireproof()), ItemGroups.COMBAT); Item LOOT_BUG_SPAWN_EGG = register("loot_bug_spawn_egg", new SpawnEggItem(UEntities.LOOT_BUG, 0x3C9D14, 0xE66F16, new Item.Settings()), ItemGroups.SPAWN_EGGS); Item BUTTERFLY_SPAWN_EGG = register("butterfly_spawn_egg", new SpawnEggItem(UEntities.BUTTERFLY, 0x222200, 0xAAEEFF, new Item.Settings()), ItemGroups.SPAWN_EGGS); From 17b014939a8f552d02cc102c9525820d22700303 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 18:35:26 +0100 Subject: [PATCH 47/81] Polearms can no longer accept the sweeping enchant. Closes #408 --- .../unicopia/item/PolearmItem.java | 10 ++++++++- .../enchantment/CustomEnchantableItem.java | 8 +++++++ .../unicopia/mixin/MixinEnchantment.java | 21 +++++++++++++++++++ .../mixin/MixinEnchantmentHelper.java | 9 ++++++++ src/main/resources/unicopia.mixin.json | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java diff --git a/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java b/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java index 5dc90908..85517dc5 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java @@ -7,14 +7,17 @@ import com.google.common.collect.Multimap; import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; +import com.minelittlepony.unicopia.item.enchantment.CustomEnchantableItem; import net.minecraft.block.*; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.*; import net.minecraft.item.*; -public class PolearmItem extends SwordItem { +public class PolearmItem extends SwordItem implements CustomEnchantableItem { static final UUID ATTACK_RANGE_MODIFIER_ID = UUID.fromString("A7B3659C-AA74-469C-963A-09A391DCAA0F"); private final Multimap attributeModifiers; @@ -65,4 +68,9 @@ public class PolearmItem extends SwordItem { return true; } + + @Override + public boolean isAcceptableEnchant(ItemStack stack, Enchantment enchantment) { + return enchantment != Enchantments.SWEEPING; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java new file mode 100644 index 00000000..5fbec700 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java @@ -0,0 +1,8 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; + +public interface CustomEnchantableItem { + boolean isAcceptableEnchant(ItemStack stack, Enchantment enchantment); +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java new file mode 100644 index 00000000..5143711c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.mixin; + +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.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.item.enchantment.CustomEnchantableItem; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; + +@Mixin(Enchantment.class) +abstract class MixinEnchantment { + @Inject(method = "isAcceptableItem", at = @At("HEAD"), cancellable = true) + private void onIsAcceptableItem(ItemStack stack, CallbackInfoReturnable info) { + if (stack.getItem() instanceof CustomEnchantableItem item && !item.isAcceptableEnchant(stack, (Enchantment)(Object)this)) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java index 4458399c..0dd1aacf 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.mixin; +import java.util.List; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -9,7 +11,9 @@ import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.EnchantmentLevelEntry; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; @Mixin(EnchantmentHelper.class) abstract class MixinEnchantmentHelper { @@ -23,4 +27,9 @@ abstract class MixinEnchantmentHelper { } }); } + + @Inject(method = "getPossibleEntries", at = @At("RETURN")) + private static void onGetPossibleEntries(int power, ItemStack stack, boolean treasureAllowed, CallbackInfoReturnable> info) { + info.getReturnValue().removeIf(entry -> !entry.enchantment.isAcceptableItem(stack)); + } } diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 17bd2121..be3b67d5 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -17,6 +17,7 @@ "MixinChunkBlockLightProvider", "MutableBlockLightStorage", "MixinDamageSource", + "MixinEnchantment", "MixinEnchantmentHelper", "MixinFallLocation", "MixinEntity", From a987e9612a5352de50ad5a88a669453b06c6682f Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 23:49:09 +0100 Subject: [PATCH 48/81] - Fixed clouds affecting lighting - Clouds no longer affect the world heightmap (fixes certain structures generating on clouds) - Added proper cloud gen beyond just structures - Fixed mobs spawning on clouds when they shouldn't --- .../block/cloud/NaturalCloudBlock.java | 18 ++- .../unicopia/mixin/MixinHeightmap.java | 21 +++ .../unicopia/server/world/UWorldGen.java | 8 + .../server/world/gen/CloudCarver.java | 142 ++++++++++++++++++ .../overworld_cloud_carver.json | 26 ++++ src/main/resources/unicopia.mixin.json | 1 + 6 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java create mode 100644 src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index 2d7325dc..cc176942 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -6,6 +6,8 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.tag.ItemTags; @@ -16,6 +18,7 @@ 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.world.BlockView; import net.minecraft.world.World; public class NaturalCloudBlock extends PoreousCloudBlock { @@ -25,10 +28,23 @@ public class NaturalCloudBlock extends PoreousCloudBlock { public NaturalCloudBlock(Settings settings, boolean meltable, @Nullable Supplier soggyBlock, Supplier compactedBlock) { - super(settings.nonOpaque(), meltable, soggyBlock); + super(settings.nonOpaque().allowsSpawning((state, world, pos, type) -> { + return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; + }), meltable, soggyBlock); this.compactedBlock = compactedBlock; } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return 0.9F; + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return true; + } + @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java new file mode 100644 index 00000000..99da4dde --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.mixin; + +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.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.block.cloud.CloudLike; + +import net.minecraft.block.BlockState; +import net.minecraft.world.Heightmap; + +@Mixin(Heightmap.class) +abstract class MixinHeightmap { + @Inject(method = "method_16682", at = @At("HEAD"), cancellable = true) + private static void excludeCloudsFromWorldSurfaceHeightMap(BlockState state, CallbackInfoReturnable info) { + if (state.getBlock() instanceof CloudLike) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java index 5100d075..2c8d1903 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.ShellsBlock; import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.server.world.gen.CaveCarvingStructureProcessor; +import com.minelittlepony.unicopia.server.world.gen.CloudCarver; import com.minelittlepony.unicopia.server.world.gen.OverworldBiomeSelectionCallback; import com.minelittlepony.unicopia.server.world.gen.SurfaceGrowthStructureProcessor; import com.minelittlepony.unicopia.util.registry.DynamicRegistry; @@ -38,6 +39,9 @@ import net.minecraft.world.biome.OverworldBiomeCreator; import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.blockpredicate.BlockPredicate; +import net.minecraft.world.gen.carver.Carver; +import net.minecraft.world.gen.carver.CaveCarverConfig; +import net.minecraft.world.gen.carver.ConfiguredCarver; import net.minecraft.world.gen.feature.ConfiguredFeatures; import net.minecraft.world.gen.feature.DefaultBiomeFeatures; import net.minecraft.world.gen.feature.Feature; @@ -126,6 +130,9 @@ public interface UWorldGen { StructureProcessorType SURFACE_GROWTH_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("surface_growth"), () -> SurfaceGrowthStructureProcessor.CODEC); StructureProcessorType CAVE_CARVING_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("cave_carving"), () -> CaveCarvingStructureProcessor.CODEC); + RegistryKey> OVERWORLD_CLOUD_CARVER_CONFIG = RegistryKey.of(RegistryKeys.CONFIGURED_CARVER, Unicopia.id("overworld_cloud_carver")); + Carver CLOUR_CARVER = Registry.register(Registries.CARVER, Unicopia.id("cloud"), new CloudCarver(CaveCarverConfig.CAVE_CODEC)); + @SafeVarargs static T applyAll(T t, Consumer ...consumers) { for (Consumer consumer : consumers) { @@ -142,6 +149,7 @@ public interface UWorldGen { .or(BiomeSelectors.tag(BiomeTags.IS_RIVER)) .or(BiomeSelectors.includeByKey(BiomeKeys.STONY_SHORE)) ), GenerationStep.Feature.VEGETAL_DECORATION, SHELLS_PLACED_FEATURE); + BiomeModifications.addCarver(BiomeSelectors.foundInOverworld(), GenerationStep.Carver.AIR, OVERWORLD_CLOUD_CARVER_CONFIG); UTreeGen.bootstrap(); OverworldBiomeSelectionCallback.EVENT.register(context -> { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java new file mode 100644 index 00000000..21356298 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -0,0 +1,142 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.function.Function; + +import com.minelittlepony.unicopia.block.UBlocks; +import com.mojang.serialization.Codec; +import net.minecraft.block.BlockState; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.carver.Carver; +import net.minecraft.world.gen.carver.CarverContext; +import net.minecraft.world.gen.carver.CarvingMask; +import net.minecraft.world.gen.carver.CaveCarver; +import net.minecraft.world.gen.carver.CaveCarverConfig; +import net.minecraft.world.gen.chunk.AquiferSampler; +import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; + +public class CloudCarver extends CaveCarver { + + private Random random; + + public CloudCarver(Codec codec) { + super(codec); + } + + @Override + protected int getMaxCaveCount() { + return 15; + } + + @Override + protected float getTunnelSystemWidth(Random random) { + return (random.nextFloat() * 2.0F + random.nextFloat()) * 2.0F; + } + + @Override + protected double getTunnelSystemHeightWidthRatio() { + return 0.5; + } + + @Override + public boolean carve( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> function, + Random random, + AquiferSampler sampler, + ChunkPos chunkPos, + CarvingMask carvingMask + ) { + this.random = random; + return super.carve(context, config, chunk, function, random, new AquiferSampler() { + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + + }, chunkPos, carvingMask); + } + + @Override + protected void carveCave( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + AquiferSampler aquiferSampler, + double x, + double y, + double z, + float xScale, + double yScale, + CarvingMask mask, + Carver.SkipPredicate skipPredicate + ) { + if (random == null) { + return; + } + int maxY = context.getMinY() + context.getHeight(); + + int bubbleCount = 10 + random.nextInt(12); + for (int i = 0; i < bubbleCount; i++) { + double width = 1.5 * xScale + random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); + } + } + + @Override + protected void carveTunnels( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + long seed, + AquiferSampler aquiferSampler, + double x, + double y, + double z, + double horizontalScale, + double verticalScale, + float w, + float yaw, + float pitch, + int branchStartIndex, + int branchCount, + double yawPitchRatio, + CarvingMask mask, + Carver.SkipPredicate skipPredicate + ) { + if (random == null) { + return; + } + int maxY = context.getMinY() + context.getHeight(); + int bubbleCount = 10 + random.nextInt(12); + for (int i = 0; i < bubbleCount; i++) { + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; + double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + random.nextFloat() * height * 0.5; + if (bubbleY + height < maxY) { + carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); + } + } + //super.carveTunnels(context, config, chunk, posToBiome, seed, aquiferSampler, x, y, z, horizontalScale, verticalScale, w, yaw, pitch, branchStartIndex, branchCount, yawPitchRatio, mask, skipPredicate); + } +} \ No newline at end of file diff --git a/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json b/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json new file mode 100644 index 00000000..b7543372 --- /dev/null +++ b/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json @@ -0,0 +1,26 @@ +{ + "type": "unicopia:cloud", + "config": { + "probability": 0.05, + "y": { + "type": "minecraft:uniform", + "min_inclusive": { + "absolute": 240 + }, + "max_inclusive": { + "absolute": 600 + } + }, + "yScale": 0.15, + "lava_level": { + "above_bottom": 8 + }, + "replaceable": "minecraft:air", + "horizontal_radius_multiplier": 3.7, + "vertical_radius_multiplier": 2.8, + "floor_level": { + "type": "minecraft:constant", + "value": 0 + } + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index be3b67d5..3079ef57 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -28,6 +28,7 @@ "MixinFallingBlockEntity", "MixinFlowableFluid", "MixinGuardianTargetPredicate", + "MixinHeightmap", "MixinItem", "MixinItemEntity", "MixinItemStack", From c32bf4c0993c5db6cbee5a24d7d692df3aa47b87 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 19:41:50 +0100 Subject: [PATCH 49/81] Tweak the cloud carver to set the top layer to soggy clouds --- .../unicopia/block/cloud/CloudBedBlock.java | 2 +- .../unicopia/block/cloud/CloudBlock.java | 13 +++++- .../unicopia/block/cloud/CloudChestBlock.java | 2 +- .../unicopia/block/cloud/CloudDoorBlock.java | 2 +- .../unicopia/block/cloud/CloudLike.java | 10 ++++- .../block/cloud/CloudStairsBlock.java | 13 +++++- .../block/cloud/NaturalCloudBlock.java | 18 +------- .../unicopia/block/cloud/Soakable.java | 2 +- .../server/world/gen/CloudCarver.java | 45 ++++++++++++++++++- 9 files changed, 82 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java index e6eb8ddf..5b8f1c69 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java @@ -24,7 +24,7 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike { private final CloudBlock baseBlock; public CloudBedBlock(String base, BlockState baseState, Settings settings) { - super(base, settings.dynamicBounds()); + super(base, CloudLike.applyCloudProperties(settings)); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 05953dc8..23e0e3f8 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -30,10 +30,21 @@ public class CloudBlock extends Block implements CloudLike { protected final boolean meltable; public CloudBlock(Settings settings, boolean meltable) { - super((meltable ? settings.ticksRandomly() : settings).nonOpaque().dynamicBounds()); + super(CloudLike.applyCloudProperties(meltable ? settings.ticksRandomly() : settings)); this.meltable = meltable; } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return 0.9F; + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return true; + } + @Override public void onEntityLand(BlockView world, Entity entity) { boolean bounce = Math.abs(entity.getVelocity().y) > 0.3; diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java index f4f5ba0b..49708712 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java @@ -77,7 +77,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike { }; public CloudChestBlock(Settings settings, BlockState baseState) { - super(settings.dynamicBounds(), () -> UBlockEntities.CLOUD_CHEST); + super(CloudLike.applyCloudProperties(settings), () -> UBlockEntities.CLOUD_CHEST); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java index e0b495d1..0e22e7ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java @@ -26,7 +26,7 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike { private final CloudBlock baseBlock; public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) { - super(settings.dynamicBounds(), blockSet); + super(CloudLike.applyCloudProperties(settings), blockSet); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java index ec9ef4fd..3684c890 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java @@ -1,5 +1,13 @@ package com.minelittlepony.unicopia.block.cloud; -public interface CloudLike { +import net.minecraft.block.Block; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +public interface CloudLike { + static Block.Settings applyCloudProperties(Block.Settings settings) { + return settings.nonOpaque().dynamicBounds().allowsSpawning((state, world, pos, type) -> { + return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; + }); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java index a2b1e4ba..5292dd2d 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java @@ -21,10 +21,21 @@ public class CloudStairsBlock extends StairsBlock implements CloudLike { private final CloudBlock baseBlock; public CloudStairsBlock(BlockState baseState, Settings settings) { - super(baseState, settings.dynamicBounds()); + super(baseState, CloudLike.applyCloudProperties(settings)); this.baseBlock = (CloudBlock)baseState.getBlock(); } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return baseBlock.getAmbientOcclusionLightLevel(state, world, pos); + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return baseBlock.isTransparent(state, world, pos); + } + @Override public void onEntityLand(BlockView world, Entity entity) { baseBlock.onEntityLand(world, entity); diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index cc176942..27a569d9 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -6,8 +6,6 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.tag.ItemTags; @@ -18,7 +16,6 @@ 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.world.BlockView; import net.minecraft.world.World; public class NaturalCloudBlock extends PoreousCloudBlock { @@ -28,23 +25,10 @@ public class NaturalCloudBlock extends PoreousCloudBlock { public NaturalCloudBlock(Settings settings, boolean meltable, @Nullable Supplier soggyBlock, Supplier compactedBlock) { - super(settings.nonOpaque().allowsSpawning((state, world, pos, type) -> { - return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; - }), meltable, soggyBlock); + super(settings, meltable, soggyBlock); this.compactedBlock = compactedBlock; } - @Override - @Deprecated - public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { - return 0.9F; - } - - @Override - public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { - return true; - } - @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java index 94ce19e8..d192c71d 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java @@ -78,7 +78,7 @@ public interface Soakable { if (moisture < 7) { world.setBlockState(pos, soakable.getStateWithMoisture(state, moisture + 1)); } - } else { + } else if (!world.isAir(pos.up())) { if (moisture > 1) { BlockPos neighborPos = pos.offset(Util.getRandom(Soakable.DIRECTIONS, random)); BlockState neighborState = world.getBlockState(neighborPos); diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index 21356298..41736d0d 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -2,12 +2,18 @@ package com.minelittlepony.unicopia.server.world.gen; import java.util.function.Function; +import org.apache.commons.lang3.mutable.MutableBoolean; + import com.minelittlepony.unicopia.block.UBlocks; import com.mojang.serialization.Codec; + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.block.BlockState; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.random.Random; import net.minecraft.world.biome.Biome; @@ -24,6 +30,8 @@ public class CloudCarver extends CaveCarver { private Random random; + private final LongSet topWrittenPositions = new LongOpenHashSet(); + public CloudCarver(Codec codec) { super(codec); } @@ -55,7 +63,7 @@ public class CloudCarver extends CaveCarver { CarvingMask carvingMask ) { this.random = random; - return super.carve(context, config, chunk, function, random, new AquiferSampler() { + boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { @Override public BlockState apply(NoisePos pos, double density) { BlockState state = sampler.apply(pos, density); @@ -68,6 +76,12 @@ public class CloudCarver extends CaveCarver { } }, chunkPos, carvingMask); + BlockPos.Mutable mutable = new BlockPos.Mutable(); + topWrittenPositions.forEach(l -> { + processSurfaceBlocks(mutable.set(l), context, config, chunk, random); + }); + topWrittenPositions.clear(); + return result; } @Override @@ -139,4 +153,33 @@ public class CloudCarver extends CaveCarver { } //super.carveTunnels(context, config, chunk, posToBiome, seed, aquiferSampler, x, y, z, horizontalScale, verticalScale, w, yaw, pitch, branchStartIndex, branchCount, yawPitchRatio, mask, skipPredicate); } + + @Override + protected boolean carveAtPoint( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + CarvingMask mask, + BlockPos.Mutable pos, + BlockPos.Mutable tmp, + AquiferSampler aquiferSampler, + MutableBoolean replacedGrassy + ) { + if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { + topWrittenPositions.remove(tmp.set(pos).move(Direction.DOWN).asLong()); + topWrittenPositions.add(pos.asLong()); + if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { + chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); + } + return true; + } + return false; + } + + protected void processSurfaceBlocks(BlockPos.Mutable pos, CarverContext context, CaveCarverConfig config, Chunk chunk, Random random) { + if (chunk.getBlockState(pos.move(Direction.UP)).isAir()) { + chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); + } + } } \ No newline at end of file From 4cfb8d835f9f71b26574e47646da9930edc88852 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 19:42:10 +0100 Subject: [PATCH 50/81] Mobs with feather falling 4 boots can now properly walk on clouds --- src/main/java/com/minelittlepony/unicopia/EquineContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/EquineContext.java b/src/main/java/com/minelittlepony/unicopia/EquineContext.java index 596c2cbb..824940de 100644 --- a/src/main/java/com/minelittlepony/unicopia/EquineContext.java +++ b/src/main/java/com/minelittlepony/unicopia/EquineContext.java @@ -22,7 +22,7 @@ public interface EquineContext { } default boolean collidesWithClouds() { - return getCompositeRace().canInteractWithClouds(); + return getCompositeRace().canInteractWithClouds() || getCloudWalkingStrength() >= 1; } default boolean hasFeatherTouch() { From 4f4ac3f8095082a56153c3d29f4c34dbd14eea9c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 20:34:53 +0100 Subject: [PATCH 51/81] Mobs with feather falling 4 boots can now walk and pathfind on clouds --- .../unicopia/InteractionManager.java | 17 +++++++++--- .../unicopia/block/cloud/CloudBedBlock.java | 2 +- .../unicopia/block/cloud/CloudBlock.java | 4 ++- .../unicopia/block/cloud/CloudChestBlock.java | 3 ++- .../unicopia/block/cloud/CloudDoorBlock.java | 8 ++++++ .../block/cloud/CloudStairsBlock.java | 2 +- .../mixin/server/MixinPathNodeMaker.java | 26 +++++++++++++++++++ .../mixin/server/MixinPlayerManager.java | 2 +- src/main/resources/unicopia.mixin.json | 1 + 9 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 5326ce75..b3fb38b8 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia; import java.util.Map; import java.util.Optional; +import java.util.Stack; import java.util.UUID; import org.jetbrains.annotations.NotNull; @@ -37,7 +38,7 @@ public class InteractionManager { @Nullable private SyncedConfig config; - private EquineContext equineContext = EquineContext.ABSENT; + private final Stack equineContext = new Stack<>(); public static InteractionManager getInstance() { return INSTANCE; @@ -109,11 +110,21 @@ public class InteractionManager { } public void setEquineContext(EquineContext context) { - equineContext = context; + equineContext.push(context); + } + + public void clearEquineContext() { + if (!equineContext.isEmpty()) { + equineContext.pop(); + } } public EquineContext getEquineContext() { - return getClientPony().map(EquineContext.class::cast).orElse(equineContext); + return getClientPony().map(EquineContext.class::cast).orElseGet(this::getPathingEquineContext); + } + + public EquineContext getPathingEquineContext() { + return equineContext.isEmpty() ? EquineContext.ABSENT : equineContext.peek(); } public Optional getClientPony() { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java index 5b8f1c69..e4d562c3 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java @@ -75,6 +75,6 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return baseState.canPathfindThrough(world, pos, type); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 23e0e3f8..6381eda2 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.block.cloud; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.block.Block; @@ -173,7 +174,8 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); + return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, EquineContext equineContext) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java index 49708712..7d53232c 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java @@ -5,6 +5,7 @@ import java.util.Optional; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.block.UBlockEntities; import net.minecraft.block.BlockState; import net.minecraft.block.ChestBlock; @@ -139,7 +140,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } public static class TileData extends ChestBlockEntity { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java index 0e22e7ea..b243a67f 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.block.cloud; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; import net.minecraft.block.BlockSetType; @@ -10,6 +11,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.DoorBlock; import net.minecraft.block.ShapeContext; import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.pathing.NavigationType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemPlacementContext; import net.minecraft.util.ActionResult; @@ -84,4 +86,10 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike { entity.setVelocity(entity.getVelocity().multiply(0.5F, 1, 0.5F)); } } + + @Override + @Deprecated + public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { + return !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds() || super.canPathfindThrough(state, world, pos, type); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java index 5292dd2d..dcff5ff1 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java @@ -97,6 +97,6 @@ public class CloudStairsBlock extends StairsBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return baseBlock.canPathfindThrough(state, world, pos, type); } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java new file mode 100644 index 00000000..9e18310c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java @@ -0,0 +1,26 @@ +package com.minelittlepony.unicopia.mixin.server; + +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.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; + +import net.minecraft.entity.ai.pathing.PathNodeMaker; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.chunk.ChunkCache; + +@Mixin(PathNodeMaker.class) +abstract class MixinPathNodeMaker { + @Inject(method = "init", at = @At("HEAD")) + private void onInit(ChunkCache cachedWorld, MobEntity entity, CallbackInfo info) { + InteractionManager.getInstance().setEquineContext(EquineContext.of(entity)); + } + + @Inject(method = "clear", at = @At("HEAD")) + private void onClear(CallbackInfo info) { + InteractionManager.getInstance().clearEquineContext(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java index 0c845c1c..271bf40a 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java @@ -44,6 +44,6 @@ abstract class MixinPlayerManager { @Inject(method = "respawnPlayer", at = @At("RETURN")) private void afterRespawnPlayer(ServerPlayerEntity player, boolean alive, CallbackInfoReturnable info) { - InteractionManager.getInstance().setEquineContext(EquineContext.ABSENT); + InteractionManager.getInstance().clearEquineContext(); } } diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 3079ef57..533483c0 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -54,6 +54,7 @@ "MixinWorld", "PointOfInterestTypesAccessor", "server.MixinEntityTrackerEntry", + "server.MixinPathNodeMaker", "server.MixinPlayerManager", "server.MixinServerPlayerEntity", "server.MixinServerPlayNetworkHandler", From 2b979d4fe4b19198394640fbe25f7ef0abb74e19 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 20:47:23 +0100 Subject: [PATCH 52/81] Skip applying the saturation shader if it's not required and remove unneccessary GL actions. Maybe Fixes #445 --- .../client/render/shader/ViewportShader.java | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) 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 21df38bc..0bda2eb9 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 @@ -9,7 +9,6 @@ import com.google.common.collect.*; import com.google.gson.JsonSyntaxException; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.entity.player.Pony; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2FloatMap; @@ -52,11 +51,7 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } } - if (shaderId == null) { - return; - } - - if (Unicopia.getConfig().disableShaders.get()) { + if (shaderId == null || Unicopia.getConfig().disableShaders.get()) { return; } @@ -81,29 +76,23 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } if (shader != null && client.player != null) { - RenderSystem.disableBlend(); - RenderSystem.disableDepthTest(); - RenderSystem.resetTextureMatrix(); - Pony pony = Pony.of(client.player); float corruption = pony.getCorruption().getScaled(0.9F); - corruption = pony.getInterpolator().interpolate("corruption", corruption, 10); + if (!MathHelper.approximatelyEquals(corruption, 0)) { + corruption = pony.getInterpolator().interpolate("corruption", corruption, 10); - corruption = 1 - corruption + 0.05F; + corruption = 1 - corruption + 0.05F; - shader.setUniformValue("color_convolve", "Saturation", corruption); - shader.render(tickDelta); + shader.setUniformValue("color_convolve", "Saturation", corruption); + shader.render(tickDelta); + } } } @Override public void reload(ResourceManager var1) { - if (shader != null) { - loadShader(shader.id); - } else { - loadShader(DESATURATION_SHADER); - } + loadShader(shader != null ? shader.id : DESATURATION_SHADER); } static class LoadedShader extends PostEffectProcessor { From 62679897b2b9c86e4102234d57bc82cb85ddcf57 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 00:40:30 +0100 Subject: [PATCH 53/81] Allow making earth pony morph using pebbles --- .../com/minelittlepony/unicopia/entity/effect/UPotions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java index 2fb07320..5709ba23 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java @@ -20,9 +20,9 @@ import net.minecraft.util.Identifier; import net.minecraft.registry.Registries; public interface UPotions { - MorphingPotion MORPH_EARTH_PONY = new MorphingPotion(Race.EARTH).registerBaseRecipes(Potions.STRENGTH, UItems.CURING_JOKE); - MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM); - MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.HIPPOGRIFF_BADGE, Items.FEATHER); + MorphingPotion MORPH_EARTH_PONY = new MorphingPotion(Race.EARTH).registerBaseRecipes(Potions.STRENGTH, UItems.CURING_JOKE, UItems.PEBBLES); + MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM, UItems.GEMSTONE); + MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER, Items.FEATHER); MorphingPotion MORPH_BAT = new MorphingPotion(Race.BAT).registerBaseRecipes(Potions.NIGHT_VISION, UItems.BUTTERFLY); MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE); MorphingPotion MORPH_KIRIN = new MorphingPotion(Race.KIRIN).registerBaseRecipes(Potions.FIRE_RESISTANCE, Items.MAGMA_CREAM); From c0d920010103a1ea94d5c6bc45779f06a03c1c21 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 00:40:50 +0100 Subject: [PATCH 54/81] Allow making changeling morph using rotten apples --- .../com/minelittlepony/unicopia/entity/effect/UPotions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java index 5709ba23..ed9c57c4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java @@ -24,7 +24,7 @@ public interface UPotions { MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM, UItems.GEMSTONE); MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER, Items.FEATHER); MorphingPotion MORPH_BAT = new MorphingPotion(Race.BAT).registerBaseRecipes(Potions.NIGHT_VISION, UItems.BUTTERFLY); - MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE); + MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE, UItems.ROTTEN_APPLE); MorphingPotion MORPH_KIRIN = new MorphingPotion(Race.KIRIN).registerBaseRecipes(Potions.FIRE_RESISTANCE, Items.MAGMA_CREAM); MorphingPotion MORPH_HIPPOGRIFF = new MorphingPotion(Race.HIPPOGRIFF).registerBaseRecipes(Potions.WATER_BREATHING, UItems.CLAM_SHELL, UItems.TURRET_SHELL, UItems.SCALLOP_SHELL); From 68820924bf94f1cdb306090de07d6508b03638fd Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 04:28:22 +0100 Subject: [PATCH 55/81] Rain no longer appears above clouds (mostly) --- .../unicopia/client/UnicopiaClient.java | 43 +++------ .../unicopia/entity/player/PlayerPhysics.java | 2 +- .../unicopia/mixin/MixinWorld.java | 40 ++++++++- .../mixin/client/MixinWorldRenderer.java | 14 +++ .../unicopia/server/world/WeatherAccess.java | 89 +++++++++++++++++++ .../server/world/WeatherConditions.java | 30 +++---- 6 files changed, 168 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index 1ad3f0a1..4e2a8ac4 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -21,7 +21,6 @@ import com.minelittlepony.unicopia.container.*; import com.minelittlepony.unicopia.entity.player.PlayerCamera; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl; -import com.minelittlepony.unicopia.server.world.WeatherConditions; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.util.Lerp; @@ -38,7 +37,6 @@ 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; @@ -55,9 +53,8 @@ public class UnicopiaClient implements ClientModInitializer { return Pony.of(MinecraftClient.getInstance().player); } - @Nullable - private Float originalRainGradient; private final Lerp rainGradient = new Lerp(0); + private final Lerp thunderGradient = new Lerp(0); public final Lerp tangentalSkyAngle = new Lerp(0, true); public final Lerp skyAngle = new Lerp(0, true); @@ -157,38 +154,22 @@ public class UnicopiaClient implements ClientModInitializer { } private void onWorldTick(ClientWorld world) { - BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos(); + /*BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos(); float tickDelta = MinecraftClient.getInstance().getTickDelta(); - Float targetRainGradient = getTargetRainGradient(world, pos, tickDelta); + Float targetRainGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : ((WeatherAccess)world).isBelowCloudLayer(pos) ? null : (Float)0F; + Float targetThunderGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : null; - if (targetRainGradient != null) { - rainGradient.update(targetRainGradient, 2000); - } + ((WeatherAccess)world).setWeatherOverride(null, null); + rainGradient.update(targetRainGradient == null ? world.getRainGradient(tickDelta) : targetRainGradient, 2000); - float gradient = rainGradient.getValue(); - if (!rainGradient.isFinished()) { - world.setRainGradient(gradient); - world.setThunderGradient(gradient); - } - } + ((WeatherAccess)world).setWeatherOverride(1F, null); + thunderGradient.update(targetThunderGradient == null ? world.getThunderGradient(tickDelta) : targetThunderGradient, 2000); - private Float getTargetRainGradient(ClientWorld world, BlockPos pos, float tickDelta) { - if (WeatherConditions.get(world).isInRangeOfStorm(pos)) { - if (originalRainGradient == null) { - originalRainGradient = world.getRainGradient(tickDelta); - } - - return 1F; - } - - if (originalRainGradient != null) { - Float f = originalRainGradient; - originalRainGradient = null; - return f; - } - - return null; + ((WeatherAccess)world).setWeatherOverride( + rainGradient.isFinished() ? targetRainGradient : (Float)rainGradient.getValue(), + thunderGradient.isFinished() ? targetThunderGradient : (Float)thunderGradient.getValue() + );*/ } private void onScreenInit(Screen screen, ButtonList buttons) { 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 01850b5b..568e1331 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -690,7 +690,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (entity.getWorld().hasRain(entity.getBlockPos())) { applyTurbulance(velocity); } else { - float targetUpdraft = (float)WeatherConditions.getUpdraft(new BlockPos.Mutable().set(entity.getBlockPos()), entity.getWorld()) / 3F; + float targetUpdraft = WeatherConditions.THERMAL_FIELD.getValue(entity.getWorld(), new BlockPos.Mutable().set(entity.getBlockPos())) / 3F; targetUpdraft *= 1 + motion; if (isGravityNegative()) { targetUpdraft *= -1; diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java index 99ca9150..f0377bb4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -1,21 +1,32 @@ package com.minelittlepony.unicopia.mixin; import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.WeatherAccess; + import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; @Mixin(World.class) -abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView { - +abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView, WeatherAccess { private final Supplier destructions = BlockDestructionManager.create((World)(Object)this); + @Nullable + private Float rainGradientOverride; + @Nullable + private Float thunderGradientOverride; + private boolean mirrorEntityStatuses; @Override @@ -28,11 +39,36 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source return destructions.get(); } + @Override + public void setWeatherOverride(Float rain, Float thunder) { + rainGradientOverride = rain; + thunderGradientOverride = thunder; + } + @Inject(method = "sendEntityStatus(Lnet/minecraft/entity/Entity;B)V", at = @At("HEAD")) private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) { if (mirrorEntityStatuses) { entity.handleStatus(status); } } + + @Inject(method = "getThunderGradient", at = @At("HEAD"), cancellable = true) + private void onGetThunderGradient(float delta, CallbackInfoReturnable info) { + if (thunderGradientOverride != null) { + info.setReturnValue(thunderGradientOverride * ((World)(Object)this).getRainGradient(delta)); + } + } + + @Inject(method = "getRainGradient", at = @At("HEAD"), cancellable = true) + private void onGetRainGradient(float delta, CallbackInfoReturnable info) { + if (rainGradientOverride != null) { + info.setReturnValue(rainGradientOverride); + } + } + + @Inject(method = "hasRain", at = @At("RETURN"), cancellable = true) + private void onHasRain(BlockPos pos, CallbackInfoReturnable info) { + info.setReturnValue((info.getReturnValue() && isBelowCloudLayer(pos)) || isInRangeOfStorm(pos)); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java index edcc852d..4dcaf112 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java @@ -15,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.minelittlepony.unicopia.client.ClientBlockDestructionManager; import com.minelittlepony.unicopia.client.UnicopiaClient; +import com.minelittlepony.unicopia.server.world.WeatherAccess; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.render.BlockBreakingInfo; import net.minecraft.client.render.Camera; @@ -22,7 +24,10 @@ import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.resource.SynchronousResourceReloader; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RotationAxis; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biome.Precipitation; @Mixin(value = WorldRenderer.class, priority = 1001) abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source { @@ -80,4 +85,13 @@ abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCl matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta))); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue())); } + + @Redirect(method = "renderWeather", at = @At(value = "INVOKE", target = "net/minecraft/world/biome/Biome.getPrecipitation(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/world/biome/Biome$Precipitation;")) + private Biome.Precipitation modifyPrecipitation(Biome biome, BlockPos pos) { + Biome.Precipitation precipitation = biome.getPrecipitation(pos); + if (!((WeatherAccess)world).isBelowClientCloudLayer(pos)) { + return Precipitation.NONE; + } + return precipitation; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java new file mode 100644 index 00000000..59f62cd5 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java @@ -0,0 +1,89 @@ +package com.minelittlepony.unicopia.server.world; + +import com.minelittlepony.unicopia.block.cloud.CloudLike; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +public interface WeatherAccess { + void setWeatherOverride(Float rain, Float thunder); + + default boolean isInRangeOfStorm(BlockPos pos) { + return WeatherConditions.get((World)this).isInRangeOfStorm(pos); + } + + @Environment(EnvType.CLIENT) + default boolean isBelowClientCloudLayer(BlockPos pos) { + + int range = MinecraftClient.isFancyGraphicsOrBetter() ? 10 : 5; + + if (pos.getY() < 230 - range) { + return true; + } + + Chunk chunk = ((World)this).getChunk(pos); + int topSection = chunk.getHighestNonEmptySection(); + + if (topSection > -1) { + int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection); + if (sectionBottomY >= pos.getY() - 16) { + BlockPos.Mutable mutable = pos.mutableCopy(); + BlockPos.Mutable probeMutable = pos.mutableCopy(); + int maxDistance = 16; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (!((World)this).isAir(probeMutable.setY(mutable.getY() + range))) { + + mutable.set(pos); + maxDistance = 16; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (((World)this).getBlockState(probeMutable.setY(mutable.getY())).getBlock() instanceof CloudLike) { + return false; + } + mutable.move(Direction.DOWN); + } + + return true; + } + mutable.move(Direction.UP); + } + } + } + return false; + } + + default boolean isBelowCloudLayer(BlockPos pos) { + if (pos.getY() < 230) { + return true; + } + + Chunk chunk = ((World)this).getChunk(pos); + int topSection = chunk.getHighestNonEmptySection(); + + if (topSection > -1) { + int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection); + if (sectionBottomY >= pos.getY() - 16) { + BlockPos.Mutable mutable = pos.mutableCopy(); + int maxDistance = 32; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (!((World)this).isAir(mutable)) { + return true; + } + mutable.move(Direction.UP); + } + } + } + return false; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java index 5199f57e..18dd1e9f 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java @@ -23,8 +23,21 @@ import net.minecraft.world.PersistentState; import net.minecraft.world.World; public class WeatherConditions extends PersistentState implements Tickable { + public static final double FIRE_UPDRAFT = 0.13; + public static final double SAND_UPDRAFT = 0.03; + public static final double SOUL_SAND_UPDRAFT = -0.03; + public static final double ICE_UPDRAFT = 0; + public static final double VOID_UPDRAFT = -0.23; + + public static final float MAX_UPDRAFT_HEIGHT = 20; + public static final float MAX_TERRAIN_HEIGHT = 50; + public static final float MAX_WIND_HEIGHT = 70; + public static final Plane HEIGHT_MAP_FIELD = (world, pos) -> world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - public static final Plane THERMAL_FIELD = (world, pos) -> (float)getUpdraft(pos, world); + public static final Plane THERMAL_FIELD = (world, pos) -> { + double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT); + return (float)(factor * getMaterialSurfaceTemperature(pos, world)); + }; public static final Plane LOCAL_ALTITUDE_FIELD = (world, pos) -> { if (!world.isAir(pos)) { return 0; @@ -36,16 +49,6 @@ public class WeatherConditions extends PersistentState implements Tickable { return y - pos.getY(); }; - public static final double FIRE_UPDRAFT = 0.13; - public static final double SAND_UPDRAFT = 0.03; - public static final double SOUL_SAND_UPDRAFT = -0.03; - public static final double ICE_UPDRAFT = 0; - public static final double VOID_UPDRAFT = -0.23; - - public static final float MAX_UPDRAFT_HEIGHT = 20; - public static final float MAX_TERRAIN_HEIGHT = 50; - public static final float MAX_WIND_HEIGHT = 70; - private static final Identifier ID = Unicopia.id("weather_conditions"); public static WeatherConditions get(World world) { @@ -176,11 +179,6 @@ public class WeatherConditions extends PersistentState implements Tickable { .multiply(windFactor); } - public static double getUpdraft(BlockPos.Mutable pos, World world) { - double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT); - return factor * getMaterialSurfaceTemperature(pos, world); - } - private static float getScaledDistanceFromTerrain(BlockPos.Mutable pos, World world, float maxDistance) { return Math.min(maxDistance, LOCAL_ALTITUDE_FIELD.getValue(world, pos)) / maxDistance; } From 5a900e8601c29659ae5c20f40c1f42b1073ad1a0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 2 Oct 2024 23:32:27 +0100 Subject: [PATCH 56/81] Remove unneccessary injection --- .../unicopia/client/BatEyesApplicator.java | 16 +++++++++++----- .../unicopia/client/UnicopiaClient.java | 7 ------- .../unicopia/mixin/client/MixinGameRenderer.java | 14 +------------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java b/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java index a3191d17..f9f26c79 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java +++ b/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java @@ -3,9 +3,9 @@ package com.minelittlepony.unicopia.client; import com.minelittlepony.unicopia.EquinePredicates; import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; -import net.minecraft.entity.player.PlayerEntity; public class BatEyesApplicator { @@ -15,11 +15,17 @@ public class BatEyesApplicator { private final MinecraftClient client = MinecraftClient.getInstance(); + public float getWorldBrightness(float initial, LivingEntity entity, float tickDelta) { + if (!EquinePredicates.PLAYER_BAT.test(entity)) { + return initial; + } + return 0.6F; + } + public void enable() { - if (client.world != null) { - PlayerEntity player = client.player; - if (!player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(player)) { - player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, 1, 1, false, false)); + if (client.world != null && client.player != null) { + if (!client.player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(client.player)) { + client.player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, -1, 1, false, false)); batEyesApplied = true; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index 4e2a8ac4..8fb1e403 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -53,9 +53,6 @@ public class UnicopiaClient implements ClientModInitializer { return Pony.of(MinecraftClient.getInstance().player); } - private final Lerp rainGradient = new Lerp(0); - private final Lerp thunderGradient = new Lerp(0); - public final Lerp tangentalSkyAngle = new Lerp(0, true); public final Lerp skyAngle = new Lerp(0, true); @@ -103,10 +100,6 @@ public class UnicopiaClient implements ClientModInitializer { return Unicopia.getConfig().preferredRace.get(); } - public static float getWorldBrightness(float initial) { - return 0.6F; - } - public UnicopiaClient() { instance = this; } 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 2fe4abe2..d9effcf6 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java @@ -6,7 +6,6 @@ import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.client.BatEyesApplicator; import com.minelittlepony.unicopia.client.UnicopiaClient; import com.minelittlepony.unicopia.client.render.shader.ViewportShader; @@ -17,7 +16,6 @@ import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.RotationAxis; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.effect.StatusEffects; import net.minecraft.resource.SynchronousResourceReloader; @Mixin(value = GameRenderer.class, priority = Integer.MAX_VALUE) @@ -46,21 +44,11 @@ abstract class MixinGameRenderer implements AutoCloseable, SynchronousResourceRe BatEyesApplicator.INSTANCE.disable(); } - @Inject(method = "getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F", - at = @At("HEAD"), - cancellable = true) - private static void onGetNightVisionStrengthHead(LivingEntity entity, float tickDelta, CallbackInfoReturnable info) { - if (!entity.hasStatusEffect(StatusEffects.NIGHT_VISION)) { - info.setReturnValue(UnicopiaClient.getWorldBrightness(0)); - } - } @Inject(method = "getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F", at = @At("RETURN"), cancellable = true) private static void onGetNightVisionStrengthReturn(LivingEntity entity, float tickDelta, CallbackInfoReturnable info) { - if (entity.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(entity)) { - info.setReturnValue(UnicopiaClient.getWorldBrightness(info.getReturnValueF())); - } + info.setReturnValue(BatEyesApplicator.INSTANCE.getWorldBrightness(info.getReturnValueF(), entity, tickDelta)); } @Inject(method = "render", From 2ad3f48f15236c08c20145e2813c605909859165 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 6 Oct 2024 18:26:44 +0100 Subject: [PATCH 57/81] Fixed muffins and rocks appearing invisible when thrown --- .../unicopia/item/HeavyProjectileItem.java | 5 +++-- .../PhysicsBodyProjectileEntity.java | 20 ++++++++++--------- .../unicopia/projectile/Projectile.java | 10 +++++----- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java b/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java index 16797e43..e76a2920 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java @@ -18,12 +18,13 @@ public class HeavyProjectileItem extends ProjectileItem { @Override public PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { - PhysicsBodyProjectileEntity projectile = player == null ? new PhysicsBodyProjectileEntity(world) : new PhysicsBodyProjectileEntity(world, player); + PhysicsBodyProjectileEntity projectile = player == null + ? new PhysicsBodyProjectileEntity(world, stack.copyWithCount(1)) + : new PhysicsBodyProjectileEntity(world, player, stack.copyWithCount(1)); if (player != null) { projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1); } projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED; - projectile.setStack(stack.copy().split(1)); return projectile; } diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java b/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java index 19b3c2bc..a831c804 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java @@ -55,16 +55,18 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl private RegistryKey damageType = UDamageTypes.ROCK; + public PhysicsBodyProjectileEntity(World world, ItemStack stack) { + super(UEntities.MUFFIN, world); + setStack(stack); + } + public PhysicsBodyProjectileEntity(EntityType type, World world) { super(type, world); } - public PhysicsBodyProjectileEntity(World world) { - this(UEntities.MUFFIN, world); - } - - public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower) { + public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower, ItemStack stack) { super(UEntities.MUFFIN, thrower, world); + setStack(stack); } @Override @@ -75,7 +77,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl } public void setStack(ItemStack stack) { - getDataTracker().set(ITEM, stack); + getDataTracker().set(ITEM, stack.copy()); } @Override @@ -89,7 +91,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl @Override protected ItemStack asItemStack() { - return getStack(); + return getStack().copy(); } public void setBouncy() { @@ -273,7 +275,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl super.writeCustomDataToNbt(nbt); ItemStack stack = getStack(); if (!stack.isEmpty()) { - nbt.put("Item", stack.writeNbt(new NbtCompound())); + nbt.put("item", stack.writeNbt(new NbtCompound())); } nbt.putString("damageType", damageType.getValue().toString()); } @@ -281,7 +283,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl @Override public void readCustomDataFromNbt(NbtCompound nbt) { super.readCustomDataFromNbt(nbt); - setStack(ItemStack.fromNbt(nbt.getCompound("Item"))); + setStack(ItemStack.fromNbt(nbt.getCompound("item"))); if (nbt.contains("damageType", NbtElement.STRING_TYPE)) { Optional.ofNullable(Identifier.tryParse(nbt.getString("damageType"))).ifPresent(id -> { setDamageType(RegistryKey.of(RegistryKeys.DAMAGE_TYPE, id)); diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java b/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java index c8b0c2a2..34f831ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java @@ -38,12 +38,12 @@ public interface Projectile extends ItemConvertible { default TypedActionResult triggerThrow(World world, PlayerEntity player, Hand hand) { ItemStack stack = player.getStackInHand(hand); - SoundEmitter.playSoundAt(player, - getThrowSound(stack), SoundCategory.NEUTRAL, - 0.5F, - 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); - if (!world.isClient) { + SoundEmitter.playSoundAt(player, + getThrowSound(stack), SoundCategory.NEUTRAL, + 0.5F, + 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); + world.spawnEntity(createProjectile(stack.copyWithCount(1), world, player)); } From 04a050658279d4ef489bc58662bca853d132cb94 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:01:58 +0100 Subject: [PATCH 58/81] Clean up soggy cloud textures slightly --- .../textures/block/soggy_cloud_side.png | Bin 7821 -> 9889 bytes .../textures/block/soggy_cloud_slab_side.png | Bin 7816 -> 9860 bytes .../textures/block/soggy_cloud_top.png | Bin 7270 -> 9420 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png index b030c4a7dceca964613f8faa473ecf333c4ff831..bfe6574f9d11dee7226150961281ca2c0895610b 100644 GIT binary patch delta 2674 zcmb7Fdr(tn7XNPEfgnkU5Lg}w1c{7s@*)o`7Dz4+#T`RXsk2Ub1Vne#K|xlna}lFL z1S6to)}_<+0o|@zT||woZfB*XONFj0YJJcZwY4HT%APMFt<(Oqy_s`!?)lF5 zJHOvK-6@T`OkMjtc7bhMPX&#?K=xe+KE{^9n{nhk!#9x$_ znFf_`b+}EBA`{}USZo%P!)CL&T#g@46u|TM=YeBYqV+%LU6fUoK*kRoS4*OXJ=;*K9p$+Hdb-{fx`z zmaoWtV`ZVOsCaeBnzftC$~Ra1VawK?_FcR8RM$8foQ(&X4mP*E<9e^NtNTxf|J-xD zx9`Khe)P8!CkM`*zu><3$)}e-r@k2a@?XPWT^$*_ar4$Ux9{A&H~#3m?;rp0Wb*0M zGpr0N^<7?VKT{?EWi$qZ&R}C@1g!!~7ciJo6-$_6Vds|yMXPskM5*;1$IfzNG}#Yl z7i=8#3zlieVjqQwsn9Tww*OCB)vwa#llG&spM;Gd9-V;s(J29X9ZinNUCm69B^jGP zDOyUikRl>LWXWMXwvZV($|XhFM2X9hC$f+zb|#I0RIqI1a>&8vRsznB8d7BCKa;yU zX%2b2&lq?WKoPb+fWR==D2#;*VB-&xqW)u~D94l9_(~e2svsl7R%RiULICChmt=@4 zL!lh;*vm4D1psJV?%MA|^ojA*#kIlu<=(B{`Xnh@Ubz@nz2IxY5tKi4?XjsQfDRJ4vt5*084Cg$U7N1zzWLb z;Ax6*J+szA=GK(B9F-U`)k4meQ4O%@Ho+kAs1bByDHg%OTo=JKov>`zfix9tLk@tA z#@axFoVFGm0ICE+R`G~;^w~0ComB|QsdydBo6wHV2}q9?_S8 zXARDQ#`MT>4uo?Wa-n4Hx|#ij(1XtCc%U^f)4gUlbQnRy_U{>_p!>^!ZfFwJt&sy1 zMv>qMP)*+3XCbBV?pei{d<3+%0QTD9yk-lS@MME^JTxmVULR8eEt7$;Ox$-SfDnza z4oZ@Rxa6f75%^T%H^IHoK>;^EFSm9K&1nFVQb1Mjfu|afgWvF_bRRQ3kXo3-emiz> z6dP#uyu6;K!MPH-MNoGMo(CqNz)Z_P$t+B12)f)heRXv5UkW#80=-tDwdu5qe4W;)(Bv1ZHQIceu_z(mIULXxs8<^_MvX?3VAN_7bQ& zp)?jkM6K1SlzQj-Ad;_DsFVt&;YZxwb3yAl!JI>v*26b}Rj@eSjMm^^BzF(rnI0ZV z-Sy)H1jaO8fAIi5b~iK4DLIDAOBz!4MHqResG|2@{@3|DYJ*U6nxp*V{88a*%irru zib92?CFekhq@Tt+`QS#|FzOdeU*B-$RImVzf7fjZb=&pgQp(UoTQ!auBqy|aY(qe^8KUs$IHIBFQft^?CTtH5A>`3ZCB2WZSBylJGCxRNeQ~9 z7BHT?x3{h)><(X7S87k|TSYyKQgU0Z)>J`m-n}=tt%3T3AFQaZoj9{L)YNL-bmWI^ z4?Z{Cymrcctz5eMTF*a?s^|3frb*t@EgPuIcWY;@JgsqG{Oq&efBbU6^P?5p+2+YW zF{O#w^)&a|@`~wgPozh(+U030+OoH}58ZE4b+n&6dRn8dtKn3cPQEa7i+LpV1H7ry zb05!1wO1MEw6wU5g~xMijSqF@<6pN;?whzx4GkVxk!HTXE$Z^y?2$u>wc>@}K78kh zIIQJJ`p%IHGD%{I{>9Y~_?ozHH>oxa+@9BDN;#3%8ZA;**V;DgSFNhv$Gf#!k=Ir( zk!T*3#*-D)i84;d!WWA>HZHK+vMPFqi*Fg$FE07V@LR9d8OoPdcbuKBY%7@B+_l9C QM}mto$={m)lA2fbKRG;mvH$=8 delta 756 zcmVr#t8K zvoi=u3IPPOeG-ZSBsMfRWHB>2IW0FhIWsLZHDh8eI59Y3EihqYGiG6CI5=WvF_SA5 zr4KeaH#aggH83Gc&@3V*iP?r~t$}lFpF9T?sU$Q{8VfWH;l|nBpTxe)a|;j?c^1%NlZ|QqFM<8!V&iXrzSO@zX#4pfLL=I)JkWU%&n!q!4ibvM0!wgy%#pwC z@2}tS>)&b>#6K^)l~@Pii(dEry)TyEsJEZ!^`!@5Jobt?Cm%koAFGINqkVtxFW05d zc?RFUzVP|?kALOJyzYzhJlShA$K>_ipK|zHo;fLm;NG{@-GA)0$s-deiqX}(RGu+s zyJbu$s4i@;j7(!9f?$(wKg1M+0qu4u#=6&5Xw8^~aE?S4wuup7m>MD+y6$UdWOlWU z2_j-f)T-rhU+e0F0}s>m^6h`gL;*189I_x_9upx#!5ov!Oyis}xw#p0;ALvpzTU1C z-OaA8Bae)TTG!f^9|qd&+Kd?9_vV~u42{h5$)Hv-35X8bO~1V(os;|RX6A&&zPTL= z$~9^ip@2bTB(uBe>Oyp6AV0Q%weJl9nTfYkDZ2X?r9%ky?ym}!+aW9@W4fDlFGh~- mwuHt!=fgB&*G3_R2LAyJ)_Jsvi9$1~x1*8>Y z+Yy2X{vjBFTBa8Q(!-gerC4=r#d_i&UiD(et7@rIrSD5f>-d+<@a??K+xOo0d++zX zH~DJbs-C?yij>~1jb2CWuWeEZMuc=)9hb;z6Sc;078FAw%OV;*M-(Cuatb0`I{qMD z&`CmsL=d9_y9jg~FTwJH?l-FAID&NH#6ckG)CGik@eWur=QDDC1mx~LgDx$;^sf?C;KtPu_g0m8llt?V5DDbWaKcbXk!6$-ElK7e}(#SGKS6RD9 z7M0w7$S=G9zDi%XqKcOLPYehQik=jsj*a8u4GBh5VoEBXHX}VFb8b#<-n{(z3yO-Z zC5ua!EM2*3b@`eP)~?%F{ozNOYBt;I?DgBW@7UR}%dxk)rS-FYpSSJr=_F*D56ysC5~VvK1pV&rOY={S1DtXYxlGtqNDWL_x%c2^vnHK+?D7D z69a_6ASbt1qgFL0Zf4miqXL&Hg?vr}Ho6^=a2S;uU<05+6HbW_kW7RoK)v`hu^&I)}E&kg2%>ZwJLmTZt)dx2c<{9H zPb5@+Mbf$4e~ePpCtG{7X|cZ&4X!w~Pf>I@MRL;6ctvUqb9DVszHmrByKibh)yYMj z-E^C+E3?#ho`t@>vh`y0fncF}neE-7y%)&9`iTeUoNis#JzIKXOV+NhBfjZ=!!T*- z7yNmyPZ`u-{_Mzd9sOnQ++<~b!IH-6vlmYsKO1`P${0us9rmve#TR4-KPUC8p=5&)x+XZkFco z;9?SdzByH>i%G@8#KI)m*uq>lH90v|*TldiP1nLG$xPS8+&I-d*~rw$&@y?lu;@}v zGfQ)GBNJ0|LnC7g3sVavE(HYzcTe8{tFY9f;>`R!TO}hsLjyfylgST71Nosghd^zf z>?kIWF19&etdVu|WtjvHvBp}D&kPIHHwnGj(Uo zw5`+F6%H`*ysG_p!HD4)$Ils#<$6kt8q>;|be;7I#F;r}>qjgwO+2ATEKO55QyA1_DQ>pPH2YZnk|(oNm>x5TJT(3FAn8kyMdowQ*-%-@Vf!GJ=n#UD6?}eZDF0Z!1h{9 z{n^i7d)EIKiJD-iXB@K8Y?AfH{=&X<@1$RU>svSdL`Th@?HWrzeAu%8ZMR6G$#JJY zmv_(0_MQ``Z}Y$IPjvCx+LEa3GqpiQ53QaBpS8Oh#?7rLQ5<1!`{U(7nScDo>x-wH T{pp|q3`_=3S3j3^P6M%D@ z6p4=o;##b3H$+rqTrHxtwz{RhOYO9@SSlTd`lw~;Y}G=I?%1;DyAZe2{bzeKH*@ay zo$ve}=Y-1*_JXxNl@Nt>q^-dZb@)^qi(!nGG34sBxmq?^2Z15iV8m$bCyc^y4C8MM zpN-K2{QGjxTM5{xcK;F)g$T2Df3g~ z5l<`W2VK}&d%{4QK$wi11iKk$M z94F=Y%xNqMhzfB2n$?1&l9WIgBBI3-NH`+Hz$=oVNP&Q&V7C$WF-k7rB9yvC!bqDV zBxR+7Y3k?}r55(TA5}hlOQo-VshJi>KNJ%imo_h5osntC$~Lk&xkV;(af!uRy0l_h z<>OUPJn5`))z&Rv@$9Plm;co8%IY<*wyayD~I5ZLf80f8D>UXZN1Hz5DtO z4IDo5*3q|*y>s%^=`&}~o&R9yQ|_~oi=U5vacS(z)oa(kzVXe(KPPX0KQ;Zsoxt6D z|3=D?(%?0#?H9`App2j>k_th}aH0W8ms0|zP8hMs7UEbLnZh)Q6onn#{qNJM`tn;* z)h`W;qg940X}2GW;bP->ZU3LN=3k{PDD8o={|Xz!q$CdgBRM&?5DUDn_PbSnPsS#f z!d4J5Y*w_Cm=#N?dYf6BWLA{p%l#gItIe!vdl)TmwV9J4SQ-NXf%b_L3fp3O!tW72 zj*2{~_HR!aHb-G)D7ylRq`@)<=iSX7bstd*Xndi=HZwh0jqyAU#UNgNH={aP}duF_ahP=YZ=ZaFoLs*=U>!47C6=rB|V)&`q1Y_YVngAMTYKUM#$k%OzgQy1-l;S(XPdzlG>m*__ z0t7%_Igtx1=YT~EXGX&`4R$N$epNUm@!mfeX2D$l&)T4$+n^4bO}?MO7QwhjRnLbn z5-|s_`G#Rb&=K&i4{1VN%aKc{c4ZZ)_ca4A&JBF{?x3H{dLW^NUx^wqN)B2z*ch}O zl=Xwea>OwiTHAysOH>L08Ypn0hXg3(qfa#9_Y|SO67n>38lIf#DA@&x-B5=@9WI#> zUcw5F-R1hnEn-5Z9LSJ(2$fTBtaUnSoEmKwW7HT7+8m9;WrQfp>2T^?&KzU5!#f(f zJKV^y`W!vO8nd$4ETi7LF)S8my}QF~vbpzpMeu#@6^1AN&*Fd~e3bC28N#T46Mq!B_ai4EI8* zIHGaMNA=^&&r0Gq9{6^w?yvPnC-+ak_{QaBt}P=yw^Z@1)>E>+(}A^9tKMk5-tk_3 zXG8pFk=&ya#etjGiq25E_9E-kqo=m(FK>R%dd_j7`GVokteas;;Jw z>u$gDVfN&A9~>Y5(exZm$$rXv-jJVMQb=F=IRDTmfxLljZp#K$i`}GPJo94*+rz4? z{?*M_7I|t5BUCn5vus}5fp5F(x)N)Y?V78_C-i}--l6*NZ*tpB4XF=LrIh)k)~?t) zQNmp(^4?M|m{wJ#tS%!h+=flH&-@`UMWt-id5_&}wOV}l54Pa~`ts;z6SY6L{mT8F zcN)KZOd|Q=`2H2=k7rn_12(WRPZ zmgZ(=X2zz576z84mWE1P3JMDDp1uKAVW~yMnfZCPN=ABy271OOlNrSV?VvV?z--nw zFtjo-0BfqqEwJ*t~c6VWr zWzc7^nxbc*Jo$iWz{AyI4YV><#_7#J9rdb&7oZTm@&C_CU|G;O;oBHgF zu_vzjG|T@q{Nj0hk}As%jZ>*F-`zjJEpdRU<-Nv%Ms9}^~d>%}lId3+b)2`q97w?<qN(-ciYol?#^8PLo8_Z_I<|;LTmiIqY8=zQ#m^Rq|WKu$GYbBvGvzaG#=Ao%Jv7$k^nx&~1%iZ&+wz znv_@IyWp>e>g#uN&o}$Qa-`iwH}qh;zh^_@XUqOiTlUEp|5zBxP#ncL|GoY#$sNy} gelV;OTJ?ax?&{Yf{eMqgfsxAK>FVdQ&MBb@0P|KK0ssI2 From add128cbee22fb00d256412094af54d489bd5b87 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:02:26 +0100 Subject: [PATCH 59/81] Use the bucket tag for filling jars instead of just the vanilla bucket --- .../unicopia/block/jar/FluidOnlyJarContents.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java index 0cdcab4b..49f0e62f 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java @@ -5,11 +5,11 @@ import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents; import com.minelittlepony.unicopia.block.ItemJarBlock.TileData; import com.minelittlepony.unicopia.util.FluidHelper; +import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; @@ -27,7 +27,7 @@ public record FluidOnlyJarContents ( @Override public TypedActionResult interact(PlayerEntity player, Hand hand) { ItemStack stack = player.getStackInHand(hand); - if (stack.isOf(Items.BUCKET)) { + if (stack.isIn(ConventionalItemTags.EMPTY_BUCKETS)) { long remainder = FluidHelper.deposit(stack, player, hand, fluid, amount); tile.markDirty(); fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1)); From c89f7209e95a89de234770acfd01d22eccaa9a9c Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:10:06 +0100 Subject: [PATCH 60/81] Fixed not being able to collect water from soggy cloud stairs --- .../unicopia/block/cloud/SoggyCloudStairsBlock.java | 11 +++++++++++ .../unicopia/block/jar/FluidOnlyJarContents.java | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java index 9e51e398..2efff68b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java @@ -8,10 +8,15 @@ import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.state.StateManager; +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.world.BlockView; +import net.minecraft.world.World; public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable { @@ -34,6 +39,12 @@ public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable return dryBlock.get().getPickStack(world, pos, state); } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryCollectMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java index 49f0e62f..b3ac0222 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java @@ -5,7 +5,7 @@ import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents; import com.minelittlepony.unicopia.block.ItemJarBlock.TileData; import com.minelittlepony.unicopia.util.FluidHelper; -import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; +import net.fabricmc.fabric.api.tag.convention.v1.ConventionalItemTags; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.minecraft.entity.player.PlayerEntity; From c877016ac78732ab7d29b1d0207482d288df5343 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:17:24 +0100 Subject: [PATCH 61/81] You can now soak clouds using bottles of water --- .../block/cloud/NaturalCloudBlock.java | 3 +- .../block/cloud/PoreousCloudBlock.java | 11 +++++++ .../block/cloud/PoreousCloudStairsBlock.java | 12 +++++++ .../unicopia/block/cloud/Soakable.java | 32 +++++++++++++------ 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index 27a569d9..e950ba4b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -29,6 +29,7 @@ public class NaturalCloudBlock extends PoreousCloudBlock { this.compactedBlock = compactedBlock; } + @Deprecated @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); @@ -41,6 +42,6 @@ public class NaturalCloudBlock extends PoreousCloudBlock { return ActionResult.SUCCESS; } - return ActionResult.PASS; + return super.onUse(state, world, pos, player, hand, hit); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java index 15303184..171b8a9e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java @@ -7,9 +7,14 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.world.ServerWorld; +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.random.Random; +import net.minecraft.world.World; public class PoreousCloudBlock extends CloudBlock implements Soakable { @Nullable @@ -20,6 +25,12 @@ public class PoreousCloudBlock extends CloudBlock implements Soakable { this.soggyBlock = soggyBlock; } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryDepositMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java index 3ee498a1..2a8e4f81 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java @@ -7,6 +7,12 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +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.world.World; public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakable { @@ -17,6 +23,12 @@ public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakabl this.soggyBlock = soggyBlock; } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryDepositMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java index d192c71d..44d6a95e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java @@ -9,8 +9,11 @@ import com.minelittlepony.unicopia.USounds; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsage; import net.minecraft.item.Items; import net.minecraft.particle.ParticleTypes; +import net.minecraft.potion.PotionUtil; +import net.minecraft.potion.Potions; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; @@ -50,15 +53,8 @@ public interface Soakable { static ActionResult tryCollectMoisture(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { if (state.getBlock() instanceof Soakable soakable) { ItemStack stack = player.getStackInHand(hand); - if (stack.getItem() == Items.GLASS_BOTTLE) { - if (!player.isCreative()) { - stack.split(1); - } - if (stack.isEmpty()) { - player.setStackInHand(hand, Items.POTION.getDefaultStack()); - } else { - player.giveItemStack(Items.POTION.getDefaultStack()); - } + if (stack.isOf(Items.GLASS_BOTTLE)) { + player.setStackInHand(hand, ItemUsage.exchangeStack(stack, player, Items.POTION.getDefaultStack(), false)); world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BOTTLE_FILL, SoundCategory.NEUTRAL, 1, 1); world.emitGameEvent(player, GameEvent.FLUID_PICKUP, pos); updateMoisture(soakable, state, world, pos, soakable.getMoisture(state) - 1); @@ -67,6 +63,24 @@ public interface Soakable { } } + return tryDepositMoisture(state, world, pos, player, hand, hit); + } + + static ActionResult tryDepositMoisture(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (state.getBlock() instanceof Soakable soakable) { + ItemStack stack = player.getStackInHand(hand); + if (soakable.getMoisture(state) < 7 + && stack.isOf(Items.POTION) + && PotionUtil.getPotion(stack) == Potions.WATER) { + player.setStackInHand(hand, ItemUsage.exchangeStack(stack, player, Items.GLASS_BOTTLE.getDefaultStack(), false)); + world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BUCKET_EMPTY, SoundCategory.NEUTRAL, 1, 1); + world.emitGameEvent(player, GameEvent.FLUID_PLACE, pos); + updateMoisture(soakable, state, world, pos, soakable.getMoisture(state) + 1); + + return ActionResult.SUCCESS; + } + } + return ActionResult.PASS; } From b61ef575fb1cf27c733afa13a09e46277bd01065 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 16:25:11 +0100 Subject: [PATCH 62/81] Fix incorrect translation --- src/main/resources/assets/unicopia/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 6005597f..df90e36b 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -799,7 +799,7 @@ "gui.unicopia.tribe_selection.options": "Available Tribes:", "gui.unicopia.tribe_selection.options.disabled": "Option Unavailable", - "gui.unicopia.tribe_selection.describe.unicopia.human": "Got it alone", + "gui.unicopia.tribe_selection.describe.unicopia.human": "Go it alone", "gui.unicopia.tribe_selection.describe.unicopia.earth": "Join the Earth Tribe", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "Join the Unicorn Tribe, master the arcane arts", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "Join the Pegasus Tribe, soar with the Wonderbolts", From 7302bd5632557e1ed02ca988684c4bf75c4d442a Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 23:07:50 +0100 Subject: [PATCH 63/81] Fixed snow gathering on clouds / clouds blocking snow from gathering below them --- .../java/com/minelittlepony/unicopia/block/UBlocks.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 521281ac..70de855b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -197,7 +197,7 @@ public interface UBlocks { Block SLIME_PUSTULE = register("slime_pustule", new SlimePustuleBlock(Settings.copy(Blocks.SLIME_BLOCK)), ItemGroups.NATURAL); Block SHAPING_BENCH = register("shaping_bench", new ShapingBenchBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL)), ItemGroups.FUNCTIONAL); - Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, + Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().notSolid().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, () -> UBlocks.SOGGY_CLOUD, () -> UBlocks.COMPACTED_CLOUD), ItemGroups.NATURAL); Block COMPACTED_CLOUD = register("compacted_cloud", new CompactedCloudBlock(CLOUD.getDefaultState())); @@ -216,14 +216,14 @@ public interface UBlocks { () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_CLOUD_BRICKS = register("compacted_cloud_bricks", new CompactedCloudBlock(CLOUD_BRICKS.getDefaultState())); Block CLOUD_BRICK_SLAB = register("cloud_brick_slab", new CloudSlabBlock(Settings.copy(CLOUD_BRICKS), false, null), ItemGroups.BUILDING_BLOCKS); - Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_BRICKS)), ItemGroups.BUILDING_BLOCKS); Block ETCHED_CLOUD = register("etched_cloud", new NaturalCloudBlock(Settings.copy(CLOUD_BRICKS), false, null, () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_ETCHED_CLOUD = register("compacted_etched_cloud", new CompactedCloudBlock(ETCHED_CLOUD.getDefaultState())); Block ETCHED_CLOUD_SLAB = register("etched_cloud_slab", new CloudSlabBlock(Settings.copy(ETCHED_CLOUD), false, null), ItemGroups.BUILDING_BLOCKS); - Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(ETCHED_CLOUD)), ItemGroups.BUILDING_BLOCKS); SoggyCloudBlock SOGGY_CLOUD = register("soggy_cloud", new SoggyCloudBlock(Settings.copy(CLOUD).hardness(0.7F), () -> UBlocks.CLOUD)); SoggyCloudSlabBlock SOGGY_CLOUD_SLAB = register("soggy_cloud_slab", new SoggyCloudSlabBlock(Settings.copy(SOGGY_CLOUD), () -> UBlocks.CLOUD_SLAB)); From adf81b9b51f2cfdcd91c8dcad163a9dc9e65d003 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 23:07:50 +0100 Subject: [PATCH 64/81] Fixed snow gathering on clouds / clouds blocking snow from gathering below them --- .../java/com/minelittlepony/unicopia/block/UBlocks.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 521281ac..70de855b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -197,7 +197,7 @@ public interface UBlocks { Block SLIME_PUSTULE = register("slime_pustule", new SlimePustuleBlock(Settings.copy(Blocks.SLIME_BLOCK)), ItemGroups.NATURAL); Block SHAPING_BENCH = register("shaping_bench", new ShapingBenchBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL)), ItemGroups.FUNCTIONAL); - Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, + Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().notSolid().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, () -> UBlocks.SOGGY_CLOUD, () -> UBlocks.COMPACTED_CLOUD), ItemGroups.NATURAL); Block COMPACTED_CLOUD = register("compacted_cloud", new CompactedCloudBlock(CLOUD.getDefaultState())); @@ -216,14 +216,14 @@ public interface UBlocks { () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_CLOUD_BRICKS = register("compacted_cloud_bricks", new CompactedCloudBlock(CLOUD_BRICKS.getDefaultState())); Block CLOUD_BRICK_SLAB = register("cloud_brick_slab", new CloudSlabBlock(Settings.copy(CLOUD_BRICKS), false, null), ItemGroups.BUILDING_BLOCKS); - Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_BRICKS)), ItemGroups.BUILDING_BLOCKS); Block ETCHED_CLOUD = register("etched_cloud", new NaturalCloudBlock(Settings.copy(CLOUD_BRICKS), false, null, () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_ETCHED_CLOUD = register("compacted_etched_cloud", new CompactedCloudBlock(ETCHED_CLOUD.getDefaultState())); Block ETCHED_CLOUD_SLAB = register("etched_cloud_slab", new CloudSlabBlock(Settings.copy(ETCHED_CLOUD), false, null), ItemGroups.BUILDING_BLOCKS); - Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(ETCHED_CLOUD)), ItemGroups.BUILDING_BLOCKS); SoggyCloudBlock SOGGY_CLOUD = register("soggy_cloud", new SoggyCloudBlock(Settings.copy(CLOUD).hardness(0.7F), () -> UBlocks.CLOUD)); SoggyCloudSlabBlock SOGGY_CLOUD_SLAB = register("soggy_cloud_slab", new SoggyCloudSlabBlock(Settings.copy(SOGGY_CLOUD), () -> UBlocks.CLOUD_SLAB)); From 02b62372cf0f6fb5afee82fa934af9fe9ab2f90d Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 9 Oct 2024 00:00:58 +0100 Subject: [PATCH 65/81] Remove debug logging --- .../java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 6381eda2..6a4adb14 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -174,7 +174,6 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } From 83048f2a6b087385728be96ca9b744aa98a6b881 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 9 Oct 2024 00:01:25 +0100 Subject: [PATCH 66/81] Remove debug logging --- .../java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 6381eda2..6a4adb14 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -174,7 +174,6 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } From 49847d14794e26aaf7be199878308c6168ffbfd0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 17:29:28 +0100 Subject: [PATCH 67/81] Fix regressions --- .../unicopia/client/gui/DismissSpellScreen.java | 5 +++++ .../unicopia/client/gui/TribeConfirmationScreen.java | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index cddf13b9..bd5833b3 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,6 +101,11 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + + } + @Override public boolean shouldPause() { return false; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java index d329b50b..41b08861 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java @@ -103,7 +103,7 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { context.getMatrices().push(); context.getMatrices().translate(0, 0, -2); if (parent != null) { @@ -112,6 +112,7 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { parent.render(context, -1, -1, delta); context.getMatrices().pop(); } + renderInGameBackground(context); final int columnHeight = 180; final int columnWidth = 310; @@ -132,9 +133,11 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50); textBody.render(context, mouseX, mouseY, delta); context.getMatrices().pop(); + context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50); - super.render(context, mouseX, mouseY, delta); + + } @Override From cab9b517c26a97396a9a7b02238338b582924724 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 18:04:05 +0100 Subject: [PATCH 68/81] Fix sweet apple acres advancement --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 5ab34f97..54553946 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.datagen.providers; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -95,7 +96,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { parent.child(UItems.TOAST).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"); parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.Items.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"); + requireAllItems(p.child(UItems.SWEET_APPLE), 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"); @@ -130,6 +131,13 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } + private AdvancementDisplayBuilder requireAllItems(AdvancementDisplayBuilder builder, ItemConvertible...items) { + List.of(items).forEach(item -> { + builder.criterion("has_" + Registries.ITEM.getId(item.asItem()).getPath(), hasItems(item)); + }); + return builder.criteriaMerger(AdvancementRequirements.CriterionMerger.AND); + } + private AdvancementDisplayBuilder applyShedFeatherCriterions(AdvancementDisplayBuilder builder, int repeats, int experience) { for (int i = 1; i <= repeats; i++) { builder.criterion("shed_feather_" + i, CustomEventCriterion.createFlying("shed_feather", i)); From 7ecf4b136790bab03eece3b1a67b2548b30129d6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 18:04:05 +0100 Subject: [PATCH 69/81] Fix sweet apple acres advancement --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 de390bfb..394516f9 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.datagen.providers; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -95,7 +96,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { parent.child(UItems.TOAST).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"); parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.Items.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"); + requireAllItems(p.child(UItems.SWEET_APPLE), 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"); @@ -130,6 +131,13 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } + private AdvancementDisplayBuilder requireAllItems(AdvancementDisplayBuilder builder, ItemConvertible...items) { + List.of(items).forEach(item -> { + builder.criterion("has_" + Registries.ITEM.getId(item.asItem()).getPath(), hasItems(item)); + }); + return builder.criteriaMerger(CriterionMerger.AND); + } + private AdvancementDisplayBuilder applyShedFeatherCriterions(AdvancementDisplayBuilder builder, int repeats, int experience) { for (int i = 1; i <= repeats; i++) { builder.criterion("shed_feather_" + i, CustomEventCriterion.createFlying("shed_feather", i)); From f1ddb2381daabd180fb2181e982756b5f6d74d02 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 19:03:48 +0100 Subject: [PATCH 70/81] Fixed the trick apple recipes # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/TrickCraftingRecipeJsonBuilder.java --- .../com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java index 127e1c42..cd7764b2 100644 --- a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java +++ b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java @@ -18,6 +18,11 @@ public class ZapAppleRecipe extends ShapelessRecipe { super(group, category, output, input); } + @Override + public RecipeSerializer getSerializer() { + return URecipes.ZAP_APPLE_SERIALIZER; + } + public static class Serializer implements RecipeSerializer { private static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.optionalFieldOf("group", "").forGetter(ZapAppleRecipe::getGroup), From 93299feae6b0be01c1393070bdb9cb225d39a352 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 18:45:49 +0100 Subject: [PATCH 71/81] Fixed the trick apple recipes # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/TrickCraftingRecipeJsonBuilder.java # src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java --- .../com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java index a92b956a..6ed7528c 100644 --- a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java +++ b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.item.UItems; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.recipe.book.CraftingRecipeCategory; import net.minecraft.util.Identifier; @@ -21,6 +22,11 @@ public class ZapAppleRecipe extends ShapelessRecipe { super(id, group, category, output, input); } + @Override + public RecipeSerializer getSerializer() { + return URecipes.ZAP_APPLE_SERIALIZER; + } + public static class Serializer extends ShapelessRecipe.Serializer { @Override public ShapelessRecipe read(Identifier identifier, JsonObject json) { From fd65e7db174862b0d2ee3295fd594af4d49a44b9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 12 Oct 2024 21:23:59 +0100 Subject: [PATCH 72/81] Change early molting season advancements to regular tasks Closes #483 --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 394516f9..4b1760fa 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -117,17 +117,17 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(Race.CHANGELING), Set.of()), 10, 90)).build(consumer, "lightning_bug"); p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(), Set.of(Race.CHANGELING)), 10, 90)).build(consumer, "wonder_bolt"); }); - parent.child(UItems.PEGASUS_FEATHER).hidden().frame(AdvancementFrame.CHALLENGE).criterion("shed_feather", CustomEventCriterion.createFlying("shed_feather")).rewards(AdvancementRewards.Builder.experience(1)).build(consumer, "molting_season_1") + parent.child(UItems.PEGASUS_FEATHER).hidden().frame(AdvancementFrame.TASK).criterion("shed_feather", CustomEventCriterion.createFlying("shed_feather")).rewards(AdvancementRewards.Builder.experience(1)).build(consumer, "molting_season_1") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2, 2)).build(consumer, "molting_season_2") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 4, 8)).build(consumer, "molting_season_3") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 8, 20)).build(consumer, "molting_season_4") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 16, 40)).build(consumer, "molting_season_5") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 32, 80)).build(consumer, "molting_season_6") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 64, 200)).build(consumer, "molting_season_7") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 128, 500)).build(consumer, "molting_season_8") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 256, 1000)).build(consumer, "molting_season_9") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 512, 2280)).build(consumer, "molting_season_10") - .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 1024, 4560)).build(consumer, "molting_season_11") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 128, 500)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_8") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 256, 1000)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_9") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 512, 2280)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_10") + .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 1024, 4560)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_11") .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } From a43f5d2022b3cb2b19725beb2b1f3513b4fc19de Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 12 Oct 2024 21:44:46 +0100 Subject: [PATCH 73/81] Fix carver crash #490 --- .../unicopia/server/world/gen/CloudCarver.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index 41736d0d..f92abb9a 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -167,7 +167,10 @@ public class CloudCarver extends CaveCarver { MutableBoolean replacedGrassy ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { - topWrittenPositions.remove(tmp.set(pos).move(Direction.DOWN).asLong()); + tmp.set(pos).move(Direction.DOWN); + if (!topWrittenPositions.isEmpty()) { + topWrittenPositions.remove(tmp.asLong()); + } topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); From 895a7bff604e09e02be96d936ac1c976dae8bf83 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 13 Oct 2024 18:18:50 +0100 Subject: [PATCH 74/81] Change criterion check to an OR for tribe joins # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java --- .../unicopia/datagen/providers/UAdvancementsProvider.java | 1 + 1 file changed, 1 insertion(+) 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 4b1760fa..42352276 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -67,6 +67,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { for (Race r : extra) { builder.criterion("be_" + r.getId().getPath(), new RaceChangeCriterion.Conditions(LootContextPredicate.EMPTY, r)); } + builder.criteriaMerger(CriterionMerger.OR); } return builder.build(consumer, race.getId().getPath() + "_route"); From 652802b8444a0184b74510263e336e07f83a35f4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 19:16:02 +0100 Subject: [PATCH 75/81] Fix #490 (again) --- .../server/world/gen/CloudCarver.java | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index f92abb9a..b4406402 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -27,11 +27,6 @@ import net.minecraft.world.gen.chunk.AquiferSampler; import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; public class CloudCarver extends CaveCarver { - - private Random random; - - private final LongSet topWrittenPositions = new LongOpenHashSet(); - public CloudCarver(Codec codec) { super(codec); } @@ -62,25 +57,13 @@ public class CloudCarver extends CaveCarver { ChunkPos chunkPos, CarvingMask carvingMask ) { - this.random = random; - boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { - @Override - public BlockState apply(NoisePos pos, double density) { - BlockState state = sampler.apply(pos, density); - return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; - } - - @Override - public boolean needsFluidTick() { - return sampler.needsFluidTick(); - } - - }, chunkPos, carvingMask); + CloudCarverContext carverContext = new CloudCarverContext(sampler, random); + boolean result = super.carve(context, config, chunk, function, random, carverContext, chunkPos, carvingMask); BlockPos.Mutable mutable = new BlockPos.Mutable(); - topWrittenPositions.forEach(l -> { + carverContext.topWrittenPositions.forEach(l -> { processSurfaceBlocks(mutable.set(l), context, config, chunk, random); }); - topWrittenPositions.clear(); + carverContext.topWrittenPositions.clear(); return result; } @@ -99,17 +82,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = 1.5 * xScale + random.nextTriangular(3, 2); - double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); - double bubbleX = x + (random.nextFloat() * 2 - 1) * width; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + double width = 1.5 * xScale +c.random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + c.random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width; carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); } } @@ -136,17 +119,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; - double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; - double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleY = y + random.nextFloat() * height * 0.5; + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + c.random.nextInt(3) + w; + double height = width * (1 + c.random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + c.random.nextFloat() * height * 0.5; if (bubbleY + height < maxY) { carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); } @@ -168,10 +151,12 @@ public class CloudCarver extends CaveCarver { ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { tmp.set(pos).move(Direction.DOWN); - if (!topWrittenPositions.isEmpty()) { - topWrittenPositions.remove(tmp.asLong()); + if (aquiferSampler instanceof CloudCarverContext c) { + if (!c.topWrittenPositions.isEmpty()) { + c.topWrittenPositions.remove(tmp.asLong()); + } + c.topWrittenPositions.add(pos.asLong()); } - topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); } @@ -185,4 +170,27 @@ public class CloudCarver extends CaveCarver { chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); } } + + static class CloudCarverContext implements AquiferSampler { + + private final AquiferSampler sampler; + public final LongSet topWrittenPositions = new LongOpenHashSet(); + public final Random random; + + public CloudCarverContext(AquiferSampler sampler, Random random) { + this.sampler = sampler; + this.random = random; + } + + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + } } \ No newline at end of file From 36eb042ffae116f552fdc22fa506c9328bc5f4cd Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 19:16:02 +0100 Subject: [PATCH 76/81] Fix #490 (again) --- .../server/world/gen/CloudCarver.java | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index f92abb9a..b4406402 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -27,11 +27,6 @@ import net.minecraft.world.gen.chunk.AquiferSampler; import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; public class CloudCarver extends CaveCarver { - - private Random random; - - private final LongSet topWrittenPositions = new LongOpenHashSet(); - public CloudCarver(Codec codec) { super(codec); } @@ -62,25 +57,13 @@ public class CloudCarver extends CaveCarver { ChunkPos chunkPos, CarvingMask carvingMask ) { - this.random = random; - boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { - @Override - public BlockState apply(NoisePos pos, double density) { - BlockState state = sampler.apply(pos, density); - return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; - } - - @Override - public boolean needsFluidTick() { - return sampler.needsFluidTick(); - } - - }, chunkPos, carvingMask); + CloudCarverContext carverContext = new CloudCarverContext(sampler, random); + boolean result = super.carve(context, config, chunk, function, random, carverContext, chunkPos, carvingMask); BlockPos.Mutable mutable = new BlockPos.Mutable(); - topWrittenPositions.forEach(l -> { + carverContext.topWrittenPositions.forEach(l -> { processSurfaceBlocks(mutable.set(l), context, config, chunk, random); }); - topWrittenPositions.clear(); + carverContext.topWrittenPositions.clear(); return result; } @@ -99,17 +82,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = 1.5 * xScale + random.nextTriangular(3, 2); - double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); - double bubbleX = x + (random.nextFloat() * 2 - 1) * width; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + double width = 1.5 * xScale +c.random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + c.random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width; carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); } } @@ -136,17 +119,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; - double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; - double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleY = y + random.nextFloat() * height * 0.5; + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + c.random.nextInt(3) + w; + double height = width * (1 + c.random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + c.random.nextFloat() * height * 0.5; if (bubbleY + height < maxY) { carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); } @@ -168,10 +151,12 @@ public class CloudCarver extends CaveCarver { ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { tmp.set(pos).move(Direction.DOWN); - if (!topWrittenPositions.isEmpty()) { - topWrittenPositions.remove(tmp.asLong()); + if (aquiferSampler instanceof CloudCarverContext c) { + if (!c.topWrittenPositions.isEmpty()) { + c.topWrittenPositions.remove(tmp.asLong()); + } + c.topWrittenPositions.add(pos.asLong()); } - topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); } @@ -185,4 +170,27 @@ public class CloudCarver extends CaveCarver { chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); } } + + static class CloudCarverContext implements AquiferSampler { + + private final AquiferSampler sampler; + public final LongSet topWrittenPositions = new LongOpenHashSet(); + public final Random random; + + public CloudCarverContext(AquiferSampler sampler, Random random) { + this.sampler = sampler; + this.random = random; + } + + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + } } \ No newline at end of file From 762c1125a305b80cfb0fd0ad1f75493b7cbfcb15 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 15 Oct 2024 11:25:51 +0100 Subject: [PATCH 77/81] Fixed rocks popping off of farmland. Fixes #493 --- .../java/com/minelittlepony/unicopia/block/RockCropBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java index b89e89b5..844dcef2 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java @@ -64,7 +64,7 @@ public class RockCropBlock extends CropBlock { }; protected RockCropBlock(Settings settings) { - super(settings); + super(settings.notSolid()); } @Override From c9e8c8a3a98b12710f41068fe39be6b95fc16c05 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 15 Oct 2024 11:25:51 +0100 Subject: [PATCH 78/81] Fixed rocks popping off of farmland. Fixes #493 --- .../java/com/minelittlepony/unicopia/block/RockCropBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java index efe80127..2a573123 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java @@ -66,7 +66,7 @@ public class RockCropBlock extends CropBlock { }; protected RockCropBlock(Settings settings) { - super(settings); + super(settings.notSolid()); } @Override From f1ea3cacb6cc5bbcaeb57d7803f68205c6e15c20 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 2 Nov 2024 16:23:44 +0000 Subject: [PATCH 79/81] Bump blockus ref --- BlockusAddon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BlockusAddon b/BlockusAddon index 2e285380..48e9b657 160000 --- a/BlockusAddon +++ b/BlockusAddon @@ -1 +1 @@ -Subproject commit 2e285380cfa55da1b858c38833f05a56666c219f +Subproject commit 48e9b6578f028d5d71471c83796984ec0322f7ef From 43fab8916bb71b829c13146b47998d0218295511 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 23:10:36 +0100 Subject: [PATCH 80/81] Fix ##520 --- .../unicopia/mixin/MixinEnchantmentHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java index 0dd1aacf..82a96870 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java @@ -8,12 +8,14 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentLevelEntry; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; @Mixin(EnchantmentHelper.class) abstract class MixinEnchantmentHelper { @@ -30,6 +32,8 @@ abstract class MixinEnchantmentHelper { @Inject(method = "getPossibleEntries", at = @At("RETURN")) private static void onGetPossibleEntries(int power, ItemStack stack, boolean treasureAllowed, CallbackInfoReturnable> info) { - info.getReturnValue().removeIf(entry -> !entry.enchantment.isAcceptableItem(stack)); + if (!stack.isOf(Items.BOOK)) { + info.getReturnValue().removeIf(entry -> entry.enchantment instanceof SimpleEnchantment && !entry.enchantment.isAcceptableItem(stack)); + } } } From f4766b08de273495de658a11c464365e5fa1babf Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 23:43:43 +0100 Subject: [PATCH 81/81] Fix #519 --- .../java/com/minelittlepony/unicopia/server/world/Tree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java index 54b57ac7..c2ee23ac 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java @@ -132,7 +132,7 @@ public record Tree ( public Tree build() { RegistryKey> configuredFeatureId = RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id); - Optional sapling = saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator(id.toString(), Optional.of(configuredFeatureId), Optional.empty(), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)); + Optional sapling = saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator(id.toString(), Optional.empty(), Optional.of(configuredFeatureId), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)); Tree tree = new Tree(id, configParameters.apply(new TreeFeatureConfig.Builder( BlockStateProvider.of(logType), trunkPlacer,