diff --git a/src/main/java/twilightforest/asmhooks/EntityHooks.java b/src/main/java/twilightforest/asmhooks/EntityHooks.java index 70c27121be..820f57a75e 100644 --- a/src/main/java/twilightforest/asmhooks/EntityHooks.java +++ b/src/main/java/twilightforest/asmhooks/EntityHooks.java @@ -5,11 +5,11 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.NeoForgeMod; import net.neoforged.neoforge.fluids.FluidType; -import org.jetbrains.annotations.Nullable; import twilightforest.init.TFDataAttachments; import twilightforest.init.custom.TravellersModifiersManager; import twilightforest.item.travellers_gear.TravellersGearLogic; @@ -25,7 +25,6 @@ public class EntityHooks { * Injection Point:
* {@link net.minecraft.world.entity.LivingEntity#canStandOnFluid(FluidState)} */ - @Nullable public static boolean processWaterWalking(boolean o, LivingEntity livingEntity, FluidState fluidState) { if (!fluidState.is(FluidTags.WATER)) return o; @@ -34,7 +33,7 @@ public static boolean processWaterWalking(boolean o, LivingEntity livingEntity, return o; boolean isWaterWalking = TravellersGearLogic.isBelowMaxWaterWalkingSubmergedHeight(livingEntity) && !livingEntity.isShiftKeyDown(); - if (livingEntity.getFluidTypeHeight(NeoForgeMod.WATER_TYPE.value()) > 0 && isWaterWalking && livingEntity.level().getGameTime() % 3 == 1) + if (livingEntity.getFluidHeight(FluidTags.WATER) > 0.0D && isWaterWalking && livingEntity.level().getGameTime() % 3 == 1) TravellersGearLogic.waterWalkingSplashEffect(livingEntity); return isWaterWalking; } @@ -99,9 +98,9 @@ public static float resetFactorWithUnrestrained(float o, Entity entity) { * {@link net.minecraft.world.entity.Entity#move(MoverType, Vec3)}
*/ public static Entity resetStuckUnrestrained(Entity entity) { - if (!(entity instanceof LivingEntity living) || living.stuckSpeedMultiplier.lengthSqr() <= 1.0E-7 || !TravellersModifiersManager.isModifierActive(entity, TravellersModifiersManager.UNRESTRAINED_MODIFIER)) + if (!(entity instanceof LivingEntity living) || !TravellersModifiersManager.isModifierActive(entity, TravellersModifiersManager.UNRESTRAINED_MODIFIER)) return entity; - living.stuckSpeedMultiplier = Vec3.ZERO; + living.makeStuckInBlock(Blocks.AIR.defaultBlockState(), Vec3.ZERO); return entity; } diff --git a/src/main/java/twilightforest/asmhooks/MultipartHooks.java b/src/main/java/twilightforest/asmhooks/MultipartHooks.java index a21d18315f..c9b3eb2099 100644 --- a/src/main/java/twilightforest/asmhooks/MultipartHooks.java +++ b/src/main/java/twilightforest/asmhooks/MultipartHooks.java @@ -3,13 +3,11 @@ import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.world.entity.Entity; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import tamaized.beanification.Autowired; -import twilightforest.asm.transformers.multipart.SendDirtyEntityDataTransformer; import twilightforest.util.multiparts.MultipartEntityUtil; import java.util.Iterator; @@ -39,7 +37,7 @@ public static Iterator resolveEntitiesForRendering(Iterator iter * Targets: {@link net.minecraft.client.renderer.entity.EntityRenderDispatcher#renderers} */ @Nullable - public static EntityRenderer resolveEntityRenderer(@Nullable EntityRenderer renderer, Entity entity) { + public static EntityRenderer resolveEntityRenderer(@Nullable EntityRenderer renderer, Entity entity) { return multipartEntityUtil.tryLookupTFPartRenderer(renderer, entity); } diff --git a/src/main/java/twilightforest/asmhooks/PlayerHooks.java b/src/main/java/twilightforest/asmhooks/PlayerHooks.java index f1aae7045b..1398796700 100644 --- a/src/main/java/twilightforest/asmhooks/PlayerHooks.java +++ b/src/main/java/twilightforest/asmhooks/PlayerHooks.java @@ -8,8 +8,6 @@ import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import twilightforest.asm.transformers.player.GetFieldOfViewModifierTransformer; -import twilightforest.asm.transformers.player.ReduceMovementFoodExhaustionTransformer; import twilightforest.init.TFAttributeModifiers; import twilightforest.init.TFDataAttachments; import twilightforest.init.TFDataComponents; diff --git a/src/main/java/twilightforest/client/event/ClientGameEvents.java b/src/main/java/twilightforest/client/event/ClientGameEvents.java index d96376a093..a65ca5a634 100644 --- a/src/main/java/twilightforest/client/event/ClientGameEvents.java +++ b/src/main/java/twilightforest/client/event/ClientGameEvents.java @@ -1,17 +1,13 @@ package twilightforest.client.event; import com.ibm.icu.text.RuleBasedNumberFormat; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.SplashRenderer; import net.minecraft.client.gui.screens.TitleScreen; -import net.minecraft.client.model.HeadedModel; -import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.rendertype.RenderTypes; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; @@ -21,8 +17,8 @@ import net.minecraft.sounds.Music; import net.minecraft.sounds.Musics; import net.minecraft.util.Mth; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.attribute.BackgroundMusic; +import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.*; import net.minecraft.world.level.ChunkPos; @@ -34,7 +30,6 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.ModList; import net.neoforged.neoforge.client.event.*; import net.neoforged.neoforge.client.gui.VanillaGuiLayers; import net.neoforged.neoforge.common.NeoForge; @@ -48,13 +43,12 @@ import twilightforest.client.*; import twilightforest.client.renderer.TFSkyRenderer; import twilightforest.client.renderer.entity.MagicPaintingRenderer; -import twilightforest.compat.curios.CuriosCompat; import twilightforest.config.TFConfig; -import twilightforest.tags.TFItemTags; import twilightforest.entity.boss.bar.ClientTFBossBar; import twilightforest.events.HostileMountEvents; import twilightforest.init.*; import twilightforest.item.*; +import twilightforest.tags.TFItemTags; import twilightforest.util.HolderMatcher; import java.time.LocalDate; @@ -95,7 +89,8 @@ private void setup() { NeoForge.EVENT_BUS.addListener(this::setMusicInDimension); NeoForge.EVENT_BUS.addListener(this::shakeCamera); NeoForge.EVENT_BUS.addListener(this::translateBookAuthor); - NeoForge.EVENT_BUS.addListener(this::unrenderHeadWithTrophies); + // Uncomment this when Curios compat is ready +// NeoForge.EVENT_BUS.addListener(this::unrenderHeadWithTrophies); NeoForge.EVENT_BUS.addListener(this::updateBowFOV); NeoForge.EVENT_BUS.addListener(CloudEvents::renderPrecipitation); @@ -139,7 +134,7 @@ private void clearEntityRenderUtilMap(ScreenEvent.Closing event) { private void setMusicInDimension(SelectMusicEvent event) { Music music = event.getOriginalMusic(); if (Minecraft.getInstance().level != null && Minecraft.getInstance().player != null && (music == Musics.CREATIVE || music == Musics.UNDER_WATER) && TFDimension.isTwilightWorldOnClient(Minecraft.getInstance().level)) { - event.setMusic(Minecraft.getInstance().level.getBiomeManager().getNoiseBiomeAtPosition(Minecraft.getInstance().player.blockPosition()).value().getBackgroundMusic().orElse(Musics.GAME)); + event.setMusic(Minecraft.getInstance().level.getBiomeManager().getNoiseBiomeAtPosition(Minecraft.getInstance().player.blockPosition()).value().getAttributes().applyModifier(EnvironmentAttributes.BACKGROUND_MUSIC, new BackgroundMusic(Musics.GAME)).defaultMusic().orElse(Musics.GAME)); } } @@ -157,30 +152,24 @@ private void removeHostileMountHealth(RenderGuiLayerEvent.Pre event) { /** * Render aurora effect as needed */ - private void renderAurora(RenderLevelStageEvent event) { + private void renderAurora(RenderLevelStageEvent.AfterWeather event) { if (Minecraft.getInstance().level == null) return; - if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_WEATHER && (aurora > 0 || lastAurora > 0) && TFShaders.AURORA != null) { + if ((aurora > 0 || lastAurora > 0) && TFShaders.AURORA != null) { Tesselator tesselator = Tesselator.getInstance(); BufferBuilder buffer = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - final float scale = 2048F * (Minecraft.getInstance().gameRenderer.getRenderDistance() / 32F); - Vec3 pos = event.getCamera().getPosition(); + final float scale = 2048F * (Minecraft.getInstance().options.getEffectiveRenderDistance() / 2F); + Vec3 pos = Minecraft.getInstance().gameRenderer.getMainCamera().position(); float y = (float) (256F - pos.y()); buffer.addVertex(-scale, y, scale).setColor(1F, 1F, 1F, 1F); buffer.addVertex(-scale, y, -scale).setColor(1F, 1F, 1F, 1F); buffer.addVertex(scale, y, -scale).setColor(1F, 1F, 1F, 1F); buffer.addVertex(scale, y, scale).setColor(1F, 1F, 1F, 1F); - RenderSystem.enableBlend(); - RenderSystem.enableDepthTest(); - RenderSystem.setShaderColor(1F, 1F, 1F, (Mth.lerp(event.getPartialTick().getGameTimeDeltaTicks(), lastAurora, aurora)) / 60F * 0.5F); TFShaders.AURORA.invokeThenEndTesselator( Minecraft.getInstance().level == null ? 0 : Mth.abs((int) Minecraft.getInstance().level.getBiomeManager().biomeZoomSeed), (float) pos.x(), (float) pos.y(), (float) pos.z(), buffer); - RenderSystem.setShaderColor(1F, 1F, 1F, 1F); - RenderSystem.disableDepthTest(); - RenderSystem.disableBlend(); } } @@ -203,9 +192,9 @@ private void clientTick(ClientTickEvent.Post event) { time++; lastAurora = aurora; - if (mc.level != null && mc.cameraEntity != null && !TFConfig.getValidAuroraBiomes(mc.level.registryAccess()).isEmpty()) { + if (mc.level != null && mc.getCameraEntity() != null && !TFConfig.getValidAuroraBiomes(mc.level.registryAccess()).isEmpty()) { RegistryAccess access = mc.level.registryAccess(); - Holder biome = mc.level.getBiome(mc.cameraEntity.blockPosition()); + Holder biome = mc.level.getBiome(mc.getCameraEntity().blockPosition()); if (TFConfig.getValidAuroraBiomes(access).stream().anyMatch(c -> holderMatcher.match(c, biome))) aurora++; else @@ -239,7 +228,7 @@ private void clientTick(ClientTickEvent.Post event) { Player player = mc.player; shakeIntensity = (float) (1.0F - mc.player.distanceToSqr(Vec3.atCenterOf(beanstalk.getBlockPos())) / Math.pow(16, 2)); if (shakeIntensity > 0) { - player.moveTo(player.getX(), player.getY(), player.getZ(), + player.snapTo(player.getX(), player.getY(), player.getZ(), player.getYRot() + (player.getRandom().nextFloat() - 0.5F) * shakeIntensity, player.getXRot() + (player.getRandom().nextFloat() * 2.5F - 1.25F) * shakeIntensity); shakeIntensity = 0.0F; @@ -289,24 +278,25 @@ private void updateBowFOV(ComputeFovModifierEvent event) { } } - private void unrenderHeadWithTrophies(RenderLivingEvent.Pre event) { - ItemStack stack = event.getEntity().getItemBySlot(EquipmentSlot.HEAD); - boolean visible = !(stack.getItem() instanceof TrophyItem) && !areCuriosEquipped(event.getEntity()); - boolean isPlayer = event.getEntity() instanceof Player; - if (event.getRenderer().getModel() instanceof HeadedModel headedModel) { - headedModel.getHead().visible = visible && (!isPlayer || headedModel.getHead().visible); // some mods like Better Combat can move player's head and hide it in the first person view - if (event.getRenderer().getModel() instanceof HumanoidModel humanoidModel) { - humanoidModel.hat.visible = visible && (!isPlayer || humanoidModel.hat.visible); - } - } - } - - private boolean areCuriosEquipped(LivingEntity entity) { - if (ModList.get().isLoaded("curios")) { - return CuriosCompat.isCurioEquippedAndVisible(entity, stack -> stack.getItem() instanceof TrophyItem); - } - return false; - } + // Uncomment this when Curios compat is ready +// private void unrenderHeadWithTrophies(RenderLivingEvent.Pre event) { +// ItemStack stack = event.getEntity().getItemBySlot(EquipmentSlot.HEAD); +// boolean visible = !(stack.getItem() instanceof TrophyItem) && !areCuriosEquipped(event.getEntity()); +// boolean isPlayer = event.getEntity() instanceof Player; +// if (event.getRenderer().getModel() instanceof HeadedModel headedModel) { +// headedModel.getHead().visible = visible && (!isPlayer || headedModel.getHead().visible); // some mods like Better Combat can move player's head and hide it in the first person view +// if (event.getRenderer().getModel() instanceof HumanoidModel humanoidModel) { +// humanoidModel.hat.visible = visible && (!isPlayer || humanoidModel.hat.visible); +// } +// } +// } +// +// private boolean areCuriosEquipped(LivingEntity entity) { +// if (ModList.get().isLoaded("curios")) { +// return CuriosCompat.isCurioEquippedAndVisible(entity, stack -> stack.getItem() instanceof TrophyItem); +// } +// return false; +// } private void translateBookAuthor(ItemTooltipEvent event) { ItemStack stack = event.getItemStack(); @@ -323,9 +313,42 @@ private void translateBookAuthor(ItemTooltipEvent event) { } } - private void renderGiantBlockOutlines(RenderHighlightEvent.Block event) { - BlockPos pos = event.getTarget().getBlockPos(); - BlockState state = event.getCamera().getEntity().level().getBlockState(pos); + // [VanillaCopy] the copy of removed LevelRenderer.renderShape + private void renderShape( + PoseStack poseStack, + VertexConsumer consumer, + VoxelShape shape, + double x, + double y, + double z, + float red, + float green, + float blue, + float alpha + ) { + PoseStack.Pose posestack$pose = poseStack.last(); + shape.forAllEdges( + (p_323073_, p_323074_, p_323075_, p_323076_, p_323077_, p_323078_) -> { + float f = (float)(p_323076_ - p_323073_); + float f1 = (float)(p_323077_ - p_323074_); + float f2 = (float)(p_323078_ - p_323075_); + float f3 = Mth.sqrt(f * f + f1 * f1 + f2 * f2); + f /= f3; + f1 /= f3; + f2 /= f3; + consumer.addVertex(posestack$pose, (float)(p_323073_ + x), (float)(p_323074_ + y), (float)(p_323075_ + z)) + .setColor(red, green, blue, alpha) + .setNormal(posestack$pose, f, f1, f2); + consumer.addVertex(posestack$pose, (float)(p_323076_ + x), (float)(p_323077_ + y), (float)(p_323078_ + z)) + .setColor(red, green, blue, alpha) + .setNormal(posestack$pose, f, f1, f2); + } + ); + } + + private void renderGiantBlockOutlines(ExtractBlockOutlineRenderStateEvent event) { + BlockPos pos = event.getBlockPos(); + BlockState state = event.getBlockState(); if (state.getBlock() instanceof MiniatureStructureBlock) { event.setCanceled(true); @@ -336,10 +359,13 @@ private void renderGiantBlockOutlines(RenderHighlightEvent.Block event) { if (player != null && (player.getMainHandItem().getItem() instanceof GiantPickItem || (player.getMainHandItem().getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof GiantBlock))) { event.setCanceled(true); if (!state.isAir() && player.level().getWorldBorder().isWithinBounds(pos)) { - BlockPos offsetPos = new BlockPos(pos.getX() & ~0b11, pos.getY() & ~0b11, pos.getZ() & ~0b11); - VertexConsumer consumer = event.getMultiBufferSource().getBuffer(RenderType.lines()); - Vec3 xyz = Vec3.atLowerCornerOf(offsetPos).subtract(event.getCamera().getPosition()); - LevelRenderer.renderShape(event.getPoseStack(), consumer, GIANT_BLOCK, xyz.x(), xyz.y(), xyz.z(), 0.0F, 0.0F, 0.0F, 0.45F); + event.addCustomRenderer((renderState, buffer, stack, translucentPass, levelRenderState) -> { + BlockPos offsetPos = new BlockPos(renderState.pos().getX() & ~0b11, renderState.pos().getY() & ~0b11, renderState.pos().getZ() & ~0b11); + Vec3 xyz = Vec3.atLowerCornerOf(offsetPos).subtract(event.getCamera().position()); + VertexConsumer consumer = buffer.getBuffer(RenderTypes.lines()); + renderShape(stack, consumer, GIANT_BLOCK, xyz.x(), xyz.y(), xyz.z(), 0.0F, 0.0F, 0.0F, 0.45F); + return true; + }); } } } diff --git a/src/main/java/twilightforest/client/event/ClientRegistrationEvents.java b/src/main/java/twilightforest/client/event/ClientRegistrationEvents.java index 06ed012b8c..2f85fa0ab7 100644 --- a/src/main/java/twilightforest/client/event/ClientRegistrationEvents.java +++ b/src/main/java/twilightforest/client/event/ClientRegistrationEvents.java @@ -20,6 +20,7 @@ import net.minecraft.client.renderer.entity.NoopRenderer; import net.minecraft.client.renderer.entity.ThrownItemRenderer; import net.minecraft.client.renderer.entity.player.AvatarRenderer; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.resources.model.sprite.AtlasManager; import net.minecraft.core.BlockPos; @@ -27,6 +28,8 @@ import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; @@ -48,7 +51,6 @@ import twilightforest.client.model.TFModelLayers; import twilightforest.client.model.armor.*; import twilightforest.client.model.block.BrazierModel; -import twilightforest.client.model.block.ReactorDebrisModel; import twilightforest.client.model.block.aurorablock.UnbakedNoiseVaryingBlockStateModel; import twilightforest.client.model.block.carpet.RoyalRagsModelLoader; import twilightforest.client.model.block.connected.ConnectedTextureModelLoader; @@ -57,7 +59,6 @@ import twilightforest.client.model.block.patch.PatchModelLoader; import twilightforest.client.model.entity.*; import twilightforest.client.model.item.TravellersGearItemModel; -import twilightforest.client.model.item.TrollsteinnModel; import twilightforest.client.particle.*; import twilightforest.client.properties.*; import twilightforest.client.renderer.armor.TFArmorRenderer; @@ -72,8 +73,7 @@ import twilightforest.client.renderer.tooltip.PotionFlaskTooltipComponent; import twilightforest.client.renderer.tooltip.TravellersBeltTooltipComponent; import twilightforest.init.*; -import twilightforest.item.ArcticArmorItem; -import twilightforest.item.PotionFlaskItem; +import twilightforest.item.*; import twilightforest.item.travellers_gear.TravellersArmorBeltItem; import twilightforest.item.travellers_gear.TravellersArmorItem; import twilightforest.item.travellers_gear.TravellersGogglesItem; @@ -89,7 +89,6 @@ public class ClientRegistrationEvents { @PostConstruct private void setup(IEventBus bus) { bus.addListener(EntityRenderersEvent.AddLayers.class, this::attachRenderLayers); - bus.addListener(this::bakeCustomModels); bus.addListener(this::cacheJarLids); bus.addListener(this::clientSetup); bus.addListener(this::registerAdditionalModels); @@ -154,20 +153,8 @@ private void registerSelectProperties(RegisterSelectItemModelPropertyEvent event event.register(TwilightForestMod.prefix("experiment_115_variant"), Experiment115Type.TYPE); } - private void bakeCustomModels(ModelEvent.ModifyBakingResult event) { - BakedModel oldModel = event.getModels().get(ModelResourceLocation.inventory(TwilightForestMod.prefix("trollsteinn"))); - models.put(ModelResourceLocation.inventory(TwilightForestMod.prefix("trollsteinn")), new TrollsteinnModel(oldModel)); - BakedModel defaultReactorDebrisModel = event.getModels().get(ModelResourceLocation.vanilla("netherrack", "")); - models.put(new ModelResourceLocation(TwilightForestMod.prefix("reactor_debris"), ""), new ReactorDebrisModel(defaultReactorDebrisModel)); - } - - private void registerAdditionalModels(ModelEvent.RegisterAdditional event) { - event.register(ShieldLayer.LOC); - event.register(ModelResourceLocation.standalone(TwilightForestMod.prefix("item/trophy"))); - event.register(ModelResourceLocation.standalone(TwilightForestMod.prefix("item/trophy_minor"))); - event.register(ModelResourceLocation.standalone(TwilightForestMod.prefix("item/trophy_quest"))); - event.register(TrollsteinnModel.LIT_TROLLSTEINN); - + // FIXME should be fixed after JarRenderer + private void registerAdditionalModels(RegisterBlockModelsEvent event) { for (JarRenderer.LidResource lid : JarRenderer.LID_LOCATION_LIST.get()) { Identifier location = lid.identifier(); String name = location.getPath(); @@ -176,11 +163,12 @@ private void registerAdditionalModels(ModelEvent.RegisterAdditional event) { } } + // FIXME should be fixed after JarRenderer private void cacheJarLids(ModelEvent.BakingCompleted event) { JarRenderer.LID_LOCATION_LIST.get().forEach((lid) -> { String name = lid.identifier().getPath(); if (lid.customPath() != null) name = lid.customPath(); - JarRenderer.LIDS.put(lid.lid(), event.getModels().get(ModelResourceLocation.standalone(TwilightForestMod.prefix("block/lid/" + name)))); + JarRenderer.LIDS.put(lid.lid(), event.getModelManager().getBlockModelSet().get(ModelResourceLocation.standalone(TwilightForestMod.prefix("block/lid/" + name)))); }); } @@ -588,18 +576,18 @@ private void attachRenderLayers(EntityRenderersEvent.AddLayers event) { BakedMultiPartRenderers.bakeMultiPartRenderers(event.getContext()); for (EntityType type : event.getEntityTypes()) { var renderer = event.getRenderer(type); - if (renderer instanceof LivingEntityRenderer living) { - attachRenderLayers(living); + if (renderer instanceof LivingEntityRenderer living) { + attachRenderLayers((LivingEntityRenderer) living); // FIXME find the better way to avoid raw types } } - event.getSkins().forEach(renderer -> { - AvatarRenderer skin = event.getPlayerRenderer(renderer); + event.getSkins().forEach(modelType -> { + AvatarRenderer skin = event.getPlayerRenderer(modelType); attachRenderLayers(Objects.requireNonNull(skin)); }); } - private > void attachRenderLayers(LivingEntityRenderer renderer) { + private > void attachRenderLayers(LivingEntityRenderer renderer) { renderer.addLayer(new ShieldLayer<>(renderer)); renderer.addLayer(new IceLayer<>(renderer)); } diff --git a/src/main/java/twilightforest/client/event/FogHandler.java b/src/main/java/twilightforest/client/event/FogHandler.java index cf8630350d..6512a831b6 100644 --- a/src/main/java/twilightforest/client/event/FogHandler.java +++ b/src/main/java/twilightforest/client/event/FogHandler.java @@ -3,12 +3,10 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.FogRenderer; import net.minecraft.util.Mth; import net.minecraft.world.level.material.FogType; import net.neoforged.neoforge.client.event.ViewportEvent; import net.neoforged.neoforge.event.level.LevelEvent; -import twilightforest.client.TwilightForestRenderInfo; import twilightforest.init.TFBiomes; import javax.annotation.Nullable; @@ -26,10 +24,9 @@ public class FogHandler { private static float TERRAIN_NEAR = 0.0F; protected static void renderFog(ViewportEvent.RenderFog event) { - if (event.getType().equals(FogType.NONE) && Minecraft.getInstance().cameraEntity instanceof LocalPlayer player && player.level() instanceof ClientLevel clientLevel && clientLevel.effects() instanceof TwilightForestRenderInfo) { - if (event.getMode().equals(FogRenderer.FogMode.FOG_SKY)) { + if (event.getType().equals(FogType.NONE) && Minecraft.getInstance().getCameraEntity() instanceof LocalPlayer player && player.level() instanceof ClientLevel clientLevel) { + if (event.getType().equals(FogType.ATMOSPHERIC)) { if (SKY_CHUNK_LOADED) { - event.setCanceled(true); boolean spooky = isSpooky(clientLevel, player); float far = spooky ? event.getFarPlaneDistance() * 0.5F : event.getFarPlaneDistance(); @@ -47,7 +44,6 @@ protected static void renderFog(ViewportEvent.RenderFog event) { } } else { if (TERRAIN_CHUNK_LOADED) { - event.setCanceled(true); boolean spooky = isSpooky(clientLevel, player); float far = spooky ? event.getFarPlaneDistance() * 0.5F : event.getFarPlaneDistance(); diff --git a/src/main/java/twilightforest/client/event/OverlayHandler.java b/src/main/java/twilightforest/client/event/OverlayHandler.java index 8587f4040a..0b22c90494 100644 --- a/src/main/java/twilightforest/client/event/OverlayHandler.java +++ b/src/main/java/twilightforest/client/event/OverlayHandler.java @@ -1,16 +1,13 @@ package twilightforest.client.event; import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.datafixers.util.Pair; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.Identifier; @@ -26,13 +23,12 @@ import twilightforest.TwilightForestMod; import tamaized.beanification.Autowired; import twilightforest.client.overlay.ItemDisplayOverlay; -import twilightforest.components.entity.TFPortalAttachment; +import twilightforest.client.overlay.PortalOverlay; import twilightforest.components.item.OreScannerData; import twilightforest.config.TFConfig; import twilightforest.entity.passive.QuestRam; import twilightforest.entity.passive.quest.ram.QuestingRamCurrentContext; import twilightforest.events.HostileMountEvents; -import twilightforest.init.TFBlocks; import twilightforest.init.TFDataAttachments; import twilightforest.init.TFDataComponents; import twilightforest.init.TFItems; @@ -57,9 +53,7 @@ protected static void registerOverlays(RegisterGuiLayersEvent event) { LocalPlayer player = minecraft.player; Gui gui = minecraft.gui; if (player != null && !minecraft.options.hideGui && TFConfig.showQuestRamCrosshairIndicator) { - RenderSystem.enableBlend(); renderIndicator(minecraft, graphics, gui, player, graphics.guiWidth(), graphics.guiHeight()); - RenderSystem.disableBlend(); } }); event.registerAbove(VanillaGuiLayers.VEHICLE_HEALTH, TwilightForestMod.prefix("hostile_mount_hunger_bar"), (graphics, partialTicks) -> { @@ -69,7 +63,7 @@ protected static void registerOverlays(RegisterGuiLayersEvent event) { if (!minecraft.options.hideGui && minecraft.gameMode.canHurtPlayer() && player != null && HostileMountEvents.isRidingUnfriendly(player)) { int xPos = graphics.guiWidth() / 2 + 91; int yPos = graphics.guiHeight() - gui.rightHeight; - gui.renderFood(graphics, player, yPos, xPos); + gui.extractFood(graphics, player, yPos, xPos); gui.rightHeight += 10; } }); @@ -93,23 +87,10 @@ protected static void registerOverlays(RegisterGuiLayersEvent event) { event.registerAboveAll(TwilightForestMod.prefix("portal_overlay"), (graphics, partialTick) -> { Minecraft minecraft = Minecraft.getInstance(); - Window window = minecraft.getWindow(); LocalPlayer player = minecraft.player; if (player != null) { - TFPortalAttachment portal = player.getData(TFDataAttachments.TF_PORTAL_COOLDOWN); - if (portal.getPortalTimer() > 0) { - RenderSystem.disableDepthTest(); - RenderSystem.depthMask(false); - RenderSystem.enableBlend(); - graphics.setColor(1.0F, 1.0F, 1.0F, (float) portal.getPortalTimer() / (float) TFPortalAttachment.MAX_TICKS); - TextureAtlasSprite textureatlassprite = minecraft.getBlockRenderer().getBlockModelShaper().getParticleIcon(TFBlocks.TWILIGHT_PORTAL.get().defaultBlockState()); - graphics.blit(0, 0, -90, window.getGuiScaledWidth(), window.getGuiScaledHeight(), textureatlassprite); - RenderSystem.disableBlend(); - RenderSystem.depthMask(true); - RenderSystem.enableDepthTest(); - graphics.setColor(1.0F, 1.0F, 1.0F, 1.0F); - } + PortalOverlay.render(graphics, minecraft, player); } }); @@ -120,21 +101,19 @@ protected static void registerOverlays(RegisterGuiLayersEvent event) { }); } - private static void renderIndicator(Minecraft minecraft, GuiGraphics graphics, Gui gui, Player player, int screenWidth, int screenHeight) { + private static void renderIndicator(Minecraft minecraft, GuiGraphicsExtractor graphics, Gui gui, Player player, int screenWidth, int screenHeight) { if (minecraft.options.getCameraType().isFirstPerson() && (minecraft.gameMode.getPlayerMode() != GameType.SPECTATOR || gui.canRenderCrosshairForSpectator(minecraft.hitResult)) && minecraft.crosshairPickEntity instanceof QuestRam ram) { - ItemStack stack = player.getInventory().getItem(player.getInventory().selected); + ItemStack stack = player.getInventory().getItem(player.getInventory().getSelectedSlot()); if (!stack.isEmpty()) { for (var questEntry : questingRamCurrentContext.getContext().questItems().entrySet()) { if (questEntry.getValue().test(stack)) { - RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); int j = ((screenHeight - 1) / 2) - 11; int k = ((screenWidth - 1) / 2) - 3; if (!ram.isColorPresent(questEntry.getKey())) { - graphics.blitSprite(QUESTING_RAM_X_SPRITE, k, j, 7, 7); + graphics.blitSprite(RenderPipelines.CROSSHAIR, QUESTING_RAM_X_SPRITE, k, j, 7, 7); } else { - graphics.blitSprite(QUESTING_RAM_CHECK_SPRITE, k, j, 7, 7); + graphics.blitSprite(RenderPipelines.CROSSHAIR, QUESTING_RAM_CHECK_SPRITE, k, j, 7, 7); } - RenderSystem.defaultBlendFunc(); break; } } @@ -142,14 +121,14 @@ private static void renderIndicator(Minecraft minecraft, GuiGraphics graphics, G } } - private static void renderShieldCount(GuiGraphics graphics, Gui gui, int screenWidth, int screenHeight, int shieldCount) { + private static void renderShieldCount(GuiGraphicsExtractor graphics, Gui gui, int screenWidth, int screenHeight, int shieldCount) { for (int i = 0; i < Math.min(shieldCount, 10); i++) { - graphics.blitSprite(FORTIFICATION_SHIELD_SPRITE, screenWidth / 2 - 91 + (i * 8), screenHeight - gui.leftHeight, 9, 9); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, FORTIFICATION_SHIELD_SPRITE, screenWidth / 2 - 91 + (i * 8), screenHeight - gui.leftHeight, 9, 9); } gui.leftHeight += 10; } - private static void renderOreMeterStats(GuiGraphics graphics, Player player) { + private static void renderOreMeterStats(GuiGraphicsExtractor graphics, Player player) { if (player.isHolding(TFItems.ORE_METER.get())) { InteractionHand handToUse = player.getItemInHand(InteractionHand.MAIN_HAND).is(TFItems.ORE_METER.get()) ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; ItemStack selectedMeter = player.getItemInHand(handToUse); @@ -160,7 +139,7 @@ private static void renderOreMeterStats(GuiGraphics graphics, Player player) { component = component.copy().append("."); } graphics.fill(0, 0, 56, 16, 0x9b000000); - graphics.drawString(Minecraft.getInstance().font, component, 4, 4, 16777215, false); + graphics.text(Minecraft.getInstance().font, component, 4, 4, 16777215, false); } else { OreScannerData oreScannerData = selectedMeter.get(TFDataComponents.ORE_DATA); @@ -189,7 +168,7 @@ private static void initTooltips(long id, int range, OreScannerData data) { int totalScanned = data.totalScannedBlocks(); List headerRowTexts = ImmutableList.of( - Component.translatable("misc.twilightforest.ore_meter_range", range, pos.x, pos.z), + Component.translatable("misc.twilightforest.ore_meter_range", range, pos.x(), pos.z()), Component.translatable("misc.twilightforest.ore_meter_total", totalScanned) ); @@ -294,11 +273,11 @@ public static ComponentColumn padding(int forcedExtraMaxWidthBySpaces) { return new ComponentColumn(List.of(), forcedExtraMaxWidthBySpaces * Minecraft.getInstance().font.width(" "), ComponentAlignment.LEFT); } - private int renderColumn(GuiGraphics graphics, ComponentColumn column, int xOff, int yOff, int verticalTextPixelsAdvance) { + private int renderColumn(GuiGraphicsExtractor graphics, ComponentColumn column, int xOff, int yOff, int verticalTextPixelsAdvance) { for (Component rowText : column.textRows) { int textPixelWidth = Minecraft.getInstance().font.width(rowText); int textXPos = xOff + this.textAlignment.getTextOffset(textPixelWidth, this.maxPixelWidth); - graphics.drawString(Minecraft.getInstance().font, rowText, textXPos, yOff, 0x00_ff_ff_ff, false); + graphics.text(Minecraft.getInstance().font, rowText, textXPos, yOff, 0x00_ff_ff_ff, false); yOff += verticalTextPixelsAdvance; } @@ -320,7 +299,7 @@ public static OreMeterInfoCache build(List headers, List 0; + if (lastImpulseZero && sameImpulseDirection && hasDoubleTapped && input.getMoveVector().x != 0) { + boolean isLeftSidestep = input.getMoveVector().x > 0; if (TravellersGearLogic.tryPerformSidestep(localPlayer, isLeftSidestep)) { localPlayer.connection.send(new PerformSidestepPacket(isLeftSidestep)); } } - localPlayer.setData(TFDataAttachments.LAST_HORIZONTAL_IMPULSE, input.leftImpulse); - if (input.leftImpulse != 0) { + localPlayer.setData(TFDataAttachments.LAST_HORIZONTAL_IMPULSE, input.getMoveVector().x); + if (input.getMoveVector().x != 0) { localPlayer.setData(TFDataAttachments.LAST_HORIZONTAL_WALKING_TIME, currentTime); - localPlayer.setData(TFDataAttachments.LAST_NON_ZERO_HORIZONTAL_IMPULSE, input.leftImpulse); + localPlayer.setData(TFDataAttachments.LAST_NON_ZERO_HORIZONTAL_IMPULSE, input.getMoveVector().x); } } @@ -242,40 +245,40 @@ private void slowZoomSensitivity(CalculatePlayerTurnEvent event) { } private boolean ignoreKeyEvent(InputEvent.Key event, KeyMapping key) { - return !key.matches(event.getKey(), event.getScanCode()) || event.getAction() != InputConstants.PRESS || Minecraft.getInstance().screen != null; + return !key.matches(event.getKeyEvent()) || event.getAction() != InputConstants.PRESS || Minecraft.getInstance().screen != null; } @SuppressWarnings("unchecked") //meh private void renderGlovesInFirstPerson(RenderArmEvent event) { - if (!TFConfig.firstPersonGloveOverlay) - return; - - AbstractClientPlayer player = event.getPlayer(); - ItemStack chestStack = player.getItemBySlot(EquipmentSlot.CHEST); - if (!chestStack.has(TFDataComponents.TRAVELLERS_HAS_GLOVES) || chestStack.has(TFDataComponents.EMPERORS_CLOTH)) - return; - - Minecraft minecraft = Minecraft.getInstance(); - EntityRenderDispatcher renderDispatcher = minecraft.getEntityRenderDispatcher(); - - if (!(renderDispatcher.getRenderer(player) instanceof AvatarRenderer avatarRenderer)) - return; - - if (!(IClientItemExtensions.of(TFItems.TRAVELLERS_GLOVES.get()).getHumanoidArmorModel(chestStack, EquipmentClientInfo.LayerType.HUMANOID, avatarRenderer.getModel()) instanceof HumanoidModel model)) - return; - - if (!(avatarRenderer.createRenderState(player, minecraft.getDeltaTracker().getGameTimeDeltaPartialTick(false)) instanceof AvatarRenderState renderState)) - return; - - renderState.attackTime = 0.0F; - renderState.isCrouching = false; - renderState.swimAmount = 0.0F; - model.setupAnim(renderState); - - ModelPart armPart = event.getArm() == HumanoidArm.RIGHT ? model.rightArm : model.leftArm; - armPart.xRot = 0.0F; - - Identifier gloveLocation = TwilightForestMod.prefix("textures/models/armor/travellers_layer_1.png"); - event.getSubmitNodeCollector().submitModelPart(armPart, event.getPoseStack(), RenderTypes.armorCutoutNoCull(gloveLocation), event.getPackedLight(), OverlayTexture.NO_OVERLAY, null); - } + if (TFConfig.firstPersonGloveOverlay) { + AbstractClientPlayer player = event.getPlayer(); + ItemStack chestStack = player.getItemBySlot(EquipmentSlot.CHEST); + if (chestStack.has(TFDataComponents.TRAVELLERS_HAS_GLOVES) && !chestStack.has(TFDataComponents.EMPERORS_CLOTH)) { + AvatarRenderer renderer = (AvatarRenderer) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player); + HumanoidModel model = (HumanoidModel) IClientItemExtensions.of(TFItems.TRAVELLERS_GLOVES.get()).getHumanoidArmorModel(chestStack, EquipmentClientInfo.LayerType.HUMANOID, renderer.getModel()); + ModelPart armPart = event.getArm() == HumanoidArm.RIGHT ? model.rightArm : model.leftArm; + AvatarRenderState renderState = renderer.createRenderState(); + renderState.attackTime = 0.0F; + renderState.isCrouching = false; + renderState.swimAmount = 0.0F; + renderState.walkAnimationPos = 0.0F; + renderState.walkAnimationSpeed = 0.0F; + renderState.ageInTicks = 0.0F; + renderState.yRot = 0.0F; + renderState.xRot = 0.0F; + model.setupAnim(renderState); + armPart.xRot = 0.0F; + Identifier gloveLocation = TwilightForestMod.prefix("textures/models/armor/travellers_layer_1.png"); + TextureAtlasSprite glove = Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(AtlasIds.ARMOR_TRIMS).getSprite(gloveLocation); + event.getSubmitNodeCollector().submitModelPart( + armPart, + event.getPoseStack(), + RenderTypes.armorCutoutNoCull(gloveLocation), + event.getPackedLight(), + OverlayTexture.NO_OVERLAY, + glove + ); + } + } + } } diff --git a/src/main/java/twilightforest/events/CapabilityEvents.java b/src/main/java/twilightforest/events/CapabilityEvents.java index f487228b61..3eb553e588 100644 --- a/src/main/java/twilightforest/events/CapabilityEvents.java +++ b/src/main/java/twilightforest/events/CapabilityEvents.java @@ -1,6 +1,7 @@ package twilightforest.events; import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -9,6 +10,8 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.storage.LevelData; +import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; @@ -26,6 +29,8 @@ @Component public class CapabilityEvents { + private static final int COMMON_INVULNERABLE_DURATION = 20; + @PostConstruct private void setup() { NeoForge.EVENT_BUS.addListener(this::updateShields); @@ -43,7 +48,7 @@ private void updateShields(EntityTickEvent.Post event) { private void updatePlayerCaps(PlayerTickEvent.Post event) { if (event.getEntity().getData(TFDataAttachments.FEATHER_FAN)) { - event.getEntity().setIgnoreFallDamageFromCurrentImpulse(true); + event.getEntity().setIgnoreFallDamageFromCurrentImpulse(true, Vec3.ZERO); event.getEntity().currentImpulseImpactPos = event.getEntity().position(); if (event.getEntity().onGround() || event.getEntity().isSwimming() || event.getEntity().isInWater()) { @@ -58,12 +63,12 @@ private void absorbShieldHits(LivingIncomingDamageEvent event) { LivingEntity living = event.getEntity(); // shields if (!living.level().isClientSide() && !event.getSource().is(DamageTypeTags.BYPASSES_ARMOR)) { - FortificationShieldAttachment attachment = living.getData(TFDataAttachments.FORTIFICATION_SHIELDS); + FortificationShieldAttachment attachment = living.getData(TFDataAttachments.FORTIFICATION_SHIELDS); if (attachment.shieldsLeft() > 0) { if (living.invulnerableTime <= 0) { attachment.breakShield(living, false); FortificationShieldAttachment.addShieldBreakParticles(event.getSource(), living); - living.invulnerableTime = living.invulnerableDuration; + living.invulnerableTime = COMMON_INVULNERABLE_DURATION; } event.setCanceled(true); } @@ -73,7 +78,7 @@ private void absorbShieldHits(LivingIncomingDamageEvent event) { private void spawnInTFIfNecessary(PlayerEvent.PlayerRespawnEvent event) { if (!(event.getEntity() instanceof ServerPlayer serverPlayer)) return; - if (serverPlayer.getRespawnPosition() == null) { + if (serverPlayer.getRespawnConfig() == null) { newSpawnInTwilightForest(serverPlayer); } } @@ -92,16 +97,18 @@ public void playerLogsIn(PlayerEvent.PlayerLoggedInEvent event) { private static void newSpawnInTwilightForest(ServerPlayer player) { if (!TFConfig.newPlayersSpawnInTF) return; - ServerLevel level = player.getServer().getLevel(TFDimension.DIMENSION_KEY); + ServerLevel level = player.level().getServer().getLevel(TFDimension.DIMENSION_KEY); if (level == null) return; BlockPos newDefaultSpawn = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, player.blockPosition()); - player.changeDimension(TFConfig.portalForNewPlayerSpawn ? + player.teleport(TFConfig.portalForNewPlayerSpawn ? TFTeleporter.createTransition(player, level, newDefaultSpawn, true) : NoReturnTeleporter.createNoPortalTransition(level, player, newDefaultSpawn)); - player.setRespawnPosition(TFDimension.DIMENSION_KEY, newDefaultSpawn, player.getYRot(), true, false); + LevelData.RespawnData respawnData = new LevelData.RespawnData(new GlobalPos(TFDimension.DIMENSION_KEY, newDefaultSpawn), player.getYRot(), player.getXRot()); + ServerPlayer.RespawnConfig respawnConfig = new ServerPlayer.RespawnConfig(respawnData, true); + player.setRespawnPosition(respawnConfig, false); player.setData(TFDataAttachments.BANISHED_TO_TWILIGHT_FOREST, Unit.INSTANCE); } @@ -110,7 +117,7 @@ private static void dataFixLegacyBanish(ServerPlayer player) { CompoundTag tagCompound = player.getPersistentData(); if (!tagCompound.contains(Player.PERSISTED_NBT_TAG)) return; - CompoundTag playerData = tagCompound.getCompound(Player.PERSISTED_NBT_TAG); + CompoundTag playerData = tagCompound.getCompoundOrEmpty(Player.PERSISTED_NBT_TAG); if (!playerData.contains("twilightforest_banished")) return; diff --git a/src/main/java/twilightforest/events/CharmEvents.java b/src/main/java/twilightforest/events/CharmEvents.java index 0ab2c55876..b60c31c381 100644 --- a/src/main/java/twilightforest/events/CharmEvents.java +++ b/src/main/java/twilightforest/events/CharmEvents.java @@ -2,23 +2,35 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.ItemStackWithSlot; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityEquipment; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.PlayerEquipment; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ResolvableProfile; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.neoforged.bus.api.EventPriority; import net.neoforged.fml.ModList; import net.neoforged.neoforge.common.NeoForge; @@ -33,13 +45,13 @@ import twilightforest.block.entity.SkullChestBlockEntity; import twilightforest.compat.curios.CuriosCompat; import twilightforest.config.TFConfig; -import twilightforest.tags.TFItemTags; import twilightforest.enums.BlockLoggingEnum; import twilightforest.init.TFBlocks; import twilightforest.init.TFItems; import twilightforest.init.TFSounds; import twilightforest.init.TFStats; import twilightforest.network.SpawnCharmPacket; +import twilightforest.tags.TFItemTags; import twilightforest.util.TFItemStackUtils; import java.util.ArrayList; @@ -51,6 +63,7 @@ public class CharmEvents { public static final String CHARM_INV_TAG = "TFCharmInventory"; public static final String CASKET_DAMAGE_TAG = "CasketDamage"; public static final String CONSUMED_CHARM_TAG = "CharmStack"; + public static final EquipmentSlot[] ARMOR_SLOTS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; @PostConstruct private void setup() { @@ -65,7 +78,7 @@ private void applyCharmOfLife(LivingDeathEvent event) { //ensure our player is real and in survival before attempting anything if (event.isCanceled() || living.level().isClientSide() || !(living instanceof Player player) || living instanceof FakePlayer || - player.isCreative() || player.isSpectator()) return; + player.isCreative() || player.isSpectator()) return; if (handleCharmOfLife(player)) event.setCanceled(true); // Executes if the player had charms } @@ -76,14 +89,16 @@ private void applyKeepingAndCasket(LivingDeathEvent event) { //ensure our player is real and in survival before attempting anything if (event.isCanceled() || living.level().isClientSide() || !(living instanceof Player player) || living instanceof FakePlayer || - player.isCreative() || player.isSpectator()) return; + player.isCreative() || player.isSpectator()) return; - if (!living.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { - // Did the player recover? No? Let's give them their stuff based on the keeping charms - handleCharmOfKeeping(player); + if (living.level() instanceof ServerLevel serverLevel) { + if (serverLevel.getGameRules().get(GameRules.KEEP_INVENTORY)) { + // Did the player recover? No? Let's give them their stuff based on the keeping charms + handleCharmOfKeeping(player); - // Then let's store the rest of their stuff in the casket - stockKeepsakeCasket(player); + // Then let's store the rest of their stuff in the casket + stockKeepsakeCasket(player); + } } } @@ -108,7 +123,7 @@ private static boolean handleCharmOfLife(Player player) { player.setHealth(player.getMaxHealth()); player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 600, 3)); - player.addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 600, 0)); + player.addEffect(new MobEffectInstance(MobEffects.RESISTANCE, 600, 0)); player.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 600, 0)); } @@ -125,44 +140,50 @@ private static boolean handleCharmOfLife(Player player) { private static void handleCharmOfKeeping(Player player) { //create a fake inventory to organize our kept inventory in - Inventory keepInventory = new Inventory(player); - ListTag tagList = new ListTag(); + Inventory keepInventory = new Inventory(player, new PlayerEquipment(player)); - if (!applyCharm(TFItems.CHARM_OF_KEEPING_3, keepInventory, player, player.getInventory().items)) { - if (!applyCharm(TFItems.CHARM_OF_KEEPING_2, keepInventory, player, player.getInventory().items.subList(0, 9))) { - int i = player.getInventory().selected; + if (!applyCharm(TFItems.CHARM_OF_KEEPING_3, keepInventory, player, player.getInventory().getNonEquipmentItems())) { + if (!applyCharm(TFItems.CHARM_OF_KEEPING_2, keepInventory, player, player.getInventory().getNonEquipmentItems().subList(0, 9))) { + int i = player.getInventory().getSelectedSlot(); if (Inventory.isHotbarSlot(i)) { - applyCharm(TFItems.CHARM_OF_KEEPING_1, keepInventory, player, NonNullList.of(player.getInventory().items.get(i))); + applyCharm(TFItems.CHARM_OF_KEEPING_1, keepInventory, player, NonNullList.of(player.getInventory().getNonEquipmentItems().get(i))); } } } //keep all items in the kept_on_death tag. This allows modpacks to support other items to keep on death - for (int i = 0; i < player.getInventory().items.size(); i++) { - ItemStack stack = player.getInventory().items.get(i); + for (int i = 0; i < player.getInventory().getNonEquipmentItems().size(); i++) { + ItemStack stack = player.getInventory().getNonEquipmentItems().get(i); if (stack.is(TFItemTags.KEPT_ON_DEATH)) { - keepInventory.items.set(i, stack.copy()); - player.getInventory().items.set(i, ItemStack.EMPTY); + keepInventory.getNonEquipmentItems().set(i, stack.copy()); + player.getInventory().getNonEquipmentItems().set(i, ItemStack.EMPTY); } } - for (int i = 0; i < player.getInventory().armor.size(); i++) { - ItemStack armor = player.getInventory().armor.get(i); + for (int i = 0; i < CharmEvents.ARMOR_SLOTS.length; i++) { + int slotIndex = i + Inventory.INVENTORY_SIZE; + ItemStack armor = player.getInventory().getItem(slotIndex); if (armor.is(TFItemTags.KEPT_ON_DEATH)) { - keepInventory.armor.set(i, armor.copy()); - player.getInventory().armor.set(i, ItemStack.EMPTY); + keepInventory.setItem(slotIndex, armor.copy()); + player.getInventory().setItem(slotIndex, ItemStack.EMPTY); } } - if (player.getInventory().offhand.getFirst().is(TFItemTags.KEPT_ON_DEATH)) { - keepInventory.offhand.set(0, player.getInventory().offhand.getFirst().copy()); - player.getInventory().offhand.set(0, ItemStack.EMPTY); + if (player.getInventory().getItem(Inventory.SLOT_OFFHAND).is(TFItemTags.KEPT_ON_DEATH)) { + keepInventory.setItem(Inventory.SLOT_OFFHAND, player.getInventory().getItem(Inventory.SLOT_OFFHAND)); + player.getInventory().setItem(Inventory.SLOT_OFFHAND, ItemStack.EMPTY); } //take our fake inventory and save it to the persistent player data. //by saving it there we can guarantee we will always get all of our items back, even if the player logs out and back in. if (!keepInventory.isEmpty()) { - keepInventory.save(tagList); + ProblemReporter.Collector reporter = new ProblemReporter.Collector(); + TagValueOutput valueOutput = TagValueOutput.createWithContext(reporter, player.level().registryAccess()); + ValueOutput.TypedOutputList typedList = valueOutput.list("items", ItemStackWithSlot.CODEC); + keepInventory.save(typedList); + CompoundTag resultTag = valueOutput.buildResult(); + ListTag tagList = resultTag.getListOrEmpty("items"); + getPlayerData(player).put(CHARM_INV_TAG, tagList); getPlayerData(player).put(CHARM_INV_TAG, tagList); } } @@ -170,8 +191,10 @@ private static void handleCharmOfKeeping(Player player) { private static boolean applyCharm(DeferredItem charm, Inventory keptInventory, Player player, List inventorySlots) { List mergedCheck = new ArrayList<>(inventorySlots); //merge armor and offhand into check slots since theyll always be kept by a charm - mergedCheck.addAll(player.getInventory().armor); - mergedCheck.addAll(player.getInventory().offhand); + for (int i = 0; i < ARMOR_SLOTS.length; i++) { + mergedCheck.add(player.getInventory().getItem(Inventory.INVENTORY_SIZE + i)); + } + mergedCheck.add(player.getInventory().getItem(Inventory.SLOT_OFFHAND)); //first, check all affected slots to make sure they arent empty. //filter out the charm so it doesnt count towards keeping items if its the only thing we are holding if (mergedCheck.stream().filter(stack -> !stack.is(charm)).allMatch(ItemStack::isEmpty)) return false; @@ -179,9 +202,9 @@ private static boolean applyCharm(DeferredItem charm, Inventory keptInvent //do we even have a charm? No? Then stop operation if (!TFItemStackUtils.consumeInventoryItem(player, charm, getPlayerData(player), true) && !hasCharmCurio(charm.value(), player)) return false; - boolean keptACasket = keepWholeListAndCheckCasket(keptInventory.items, inventorySlots, charm == TFItems.CHARM_OF_KEEPING_3); - keptACasket = keepWholeListAndCheckCasket(keptInventory.armor, player.getInventory().armor, keptACasket); - keepWholeListAndCheckCasket(keptInventory.offhand, player.getInventory().offhand, keptACasket); + boolean keptACasket = keepWholeListAndCheckCasket(keptInventory.getNonEquipmentItems(), inventorySlots, charm == TFItems.CHARM_OF_KEEPING_3); + keptACasket = keepWholeListAndCheckCasket(keptInventory, player.getInventory(), 0, Inventory.INVENTORY_SIZE, keptACasket); + keepWholeListAndCheckCasket(keptInventory, player.getInventory(), Inventory.SLOT_OFFHAND, Inventory.SLOT_OFFHAND + 1, keptACasket); return true; } @@ -216,7 +239,7 @@ private static void stockKeepsakeCasket(Player player) { BlockPos immutablePos = pos.immutable(); FluidState fluidState = level.getFluidState(immutablePos); - int damage = getPlayerData(player).contains(CASKET_DAMAGE_TAG) ? getPlayerData(player).getInt(CASKET_DAMAGE_TAG) : 0; + int damage = getPlayerData(player).getIntOr(CASKET_DAMAGE_TAG, 0); BlockState setState = TFBlocks.KEEPSAKE_CASKET.get().defaultBlockState() .setValue(BlockLoggingEnum.MULTILOGGED, BlockLoggingEnum.getFromFluid(fluidState.getType())) .setValue(KeepsakeCasketBlock.BREAKAGE, damage) @@ -245,7 +268,7 @@ private static void stockKeepsakeCasket(Player player) { if (TFConfig.casketUUIDLocking) { //make it so only the player who died can open the chest if our config allows us - casket.owner = new ResolvableProfile(player.getGameProfile()); + casket.owner = ResolvableProfile.createResolved(player.getGameProfile()); } else { casket.owner = null; } @@ -260,24 +283,34 @@ private static void stockKeepsakeCasket(Player player) { // lets add our inventory exactly how it was on us list.addAll(TFItemStackUtils.sortArmorForCasket(player)); - player.getInventory().armor.clear(); list.addAll(filler); - list.addAll(player.getInventory().offhand); - player.getInventory().offhand.clear(); + list.add(player.getInventory().getItem(Inventory.SLOT_OFFHAND)); list.addAll(TFItemStackUtils.sortInvForCasket(player)); - player.getInventory().items.clear(); + player.getInventory().clearContent(); casket.setItems(NonNullList.of(ItemStack.EMPTY, list.toArray(new ItemStack[casketCapacity]))); getPlayerData(player).remove(CASKET_DAMAGE_TAG); } else { //inventory is empty minus the casket: put the casket into the kept inventory for (int i = 0; i < player.getInventory().getContainerSize(); i++) { - if (player.getInventory().getItem(i).is(TFItems.KEEPSAKE_CASKET)) { - Inventory tmp = new Inventory(player); - tmp.load(getPlayerData(player).getList(CHARM_INV_TAG, 10)); + if (player.getInventory().getItem(i).is(TFItems.KEEPSAKE_CASKET.get())) { + Inventory tmp = new Inventory(player, new PlayerEquipment(player)); + ListTag savedListTag = getPlayerData(player).getListOrEmpty(CHARM_INV_TAG); + CompoundTag rootLoadTag = new CompoundTag(); + rootLoadTag.put("items", savedListTag); + ProblemReporter.Collector loadReporter = new ProblemReporter.Collector(); + ValueInput valueInput = TagValueInput.create(loadReporter, player.level().registryAccess(), rootLoadTag); + ValueInput.TypedInputList typedInputList = valueInput.listOrEmpty("items", ItemStackWithSlot.CODEC); + tmp.load(typedInputList); tmp.add(player.getInventory().getItem(i).copy()); player.getInventory().setItem(i, ItemStack.EMPTY); - getPlayerData(player).put(CHARM_INV_TAG, tmp.save(new ListTag())); + ProblemReporter.Collector saveReporter = new ProblemReporter.Collector(); + TagValueOutput valueOutput = TagValueOutput.createWithContext(saveReporter, player.level().registryAccess()); + ValueOutput.TypedOutputList typedOutputList = valueOutput.list("items", ItemStackWithSlot.CODEC); + tmp.save(typedOutputList); + CompoundTag resultTag = valueOutput.buildResult(); + ListTag finalTagList = resultTag.getListOrEmpty("items"); + getPlayerData(player).put(CHARM_INV_TAG, finalTagList); } } } @@ -293,15 +326,18 @@ private static void returnStoredItems(Player player) { //check if our tag is in the persistent player data. If so, copy that inventory over to our own. Cloud storage at its finest! CompoundTag playerData = getPlayerData(player); if (!player.level().isClientSide() && playerData.contains(CHARM_INV_TAG)) { - ListTag tagList = playerData.getList(CHARM_INV_TAG, 10); + ListTag tagList = playerData.getListOrEmpty(CHARM_INV_TAG); TFItemStackUtils.loadNoClear(player.registryAccess(), tagList, player.getInventory()); - getPlayerData(player).getList(CHARM_INV_TAG, 10).clear(); + getPlayerData(player).getListOrEmpty(CHARM_INV_TAG).clear(); getPlayerData(player).remove(CHARM_INV_TAG); } // spawn effect thingers if (getPlayerData(player).contains(CONSUMED_CHARM_TAG)) { - ItemStack stack = ItemStack.parseOptional(player.registryAccess(), (CompoundTag) getPlayerData(player).get(CONSUMED_CHARM_TAG)); + CompoundTag tag = (CompoundTag) getPlayerData(player).get(CONSUMED_CHARM_TAG); + HolderLookup.Provider lookupProvider = player.registryAccess(); + ItemStack parsedStack = ItemStack.CODEC.parse(lookupProvider.createSerializationContext(NbtOps.INSTANCE), tag).resultOrPartial().orElse(ItemStack.EMPTY); + ItemStack stack = tag.isEmpty() ? ItemStack.EMPTY : parsedStack; if (player instanceof ServerPlayer serverPlayer) { PacketDistributor.sendToPlayer(serverPlayer, new SpawnCharmPacket(stack, TFSounds.CHARM_KEEP.getKey())); @@ -315,7 +351,7 @@ public static CompoundTag getPlayerData(Player player) { if (!player.getPersistentData().contains(Player.PERSISTED_NBT_TAG)) { player.getPersistentData().put(Player.PERSISTED_NBT_TAG, new CompoundTag()); } - return player.getPersistentData().getCompound(Player.PERSISTED_NBT_TAG); + return player.getPersistentData().getCompoundOrEmpty(Player.PERSISTED_NBT_TAG); } //transfers a list of items to another @@ -338,6 +374,26 @@ private static boolean keepWholeListAndCheckCasket(NonNullList transf return keptCasket || skipCasketCheck; } + //transfers content from some slots to another slots + private static boolean keepWholeListAndCheckCasket(Inventory transferTo, Inventory transferFrom, int fromSlot, int toSlot, boolean skipCasketCheck) { + boolean keptCasket = false; + for (int i = fromSlot; i < toSlot; i++) { + var item = transferFrom.getItem(i).copy(); + if (skipCasketCheck || (!item.is(TFItems.KEEPSAKE_CASKET) || keptCasket)) { + transferTo.setItem(i, item); + transferFrom.setItem(i, ItemStack.EMPTY); + } else { + keptCasket = true; + if (item.getCount() > 1) { + item.shrink(1); + transferTo.setItem(i, item); + transferFrom.setItem(i, item.copyWithCount(1)); + } + } + } + return keptCasket || skipCasketCheck; + } + private static boolean hasCharmCurio(Item item, Player player) { if (ModList.get().isLoaded("curios")) { return CuriosCompat.findAndConsumeCurio(item, player); diff --git a/src/main/java/twilightforest/events/EntityEvents.java b/src/main/java/twilightforest/events/EntityEvents.java index b24a523923..bfaa7f4328 100644 --- a/src/main/java/twilightforest/events/EntityEvents.java +++ b/src/main/java/twilightforest/events/EntityEvents.java @@ -20,9 +20,10 @@ import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.monster.EnderMan; -import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.monster.zombie.Zombie; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.projectile.ProjectileDeflection; @@ -34,10 +35,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.biome.MobSpawnSettings; -import net.minecraft.world.level.block.AbstractSkullBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SkullBlock; -import net.minecraft.world.level.block.WallSkullBlock; +import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.SkullBlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -46,6 +44,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.EntityHitResult; import net.neoforged.fml.ModList; +import net.neoforged.neoforge.client.network.ClientPacketDistributor; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.damagesource.DamageContainer; import net.neoforged.neoforge.event.EventHooks; @@ -55,12 +54,10 @@ import net.neoforged.neoforge.event.entity.living.*; import net.neoforged.neoforge.event.entity.player.AdvancementEvent; import net.neoforged.neoforge.event.entity.player.AttackEntityEvent; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; -import net.neoforged.neoforge.event.level.BlockEvent; import net.neoforged.neoforge.event.level.ExplosionEvent; import net.neoforged.neoforge.event.level.LevelEvent; -import net.neoforged.neoforge.items.ItemHandlerHelper; +import net.neoforged.neoforge.event.level.block.BreakBlockEvent; import net.neoforged.neoforge.network.PacketDistributor; import tamaized.beanification.PostConstruct; import twilightforest.TwilightForestMod; @@ -71,7 +68,6 @@ import twilightforest.block.entity.SkullChestBlockEntity; import twilightforest.components.item.SkullCandles; import twilightforest.config.TFConfig; -import twilightforest.tags.TFEntityTypeTags; import twilightforest.enchantment.ApplyFrostedEffect; import twilightforest.entity.passive.quest.ram.QuestingRamCurrentContext; import twilightforest.entity.projectile.ITFProjectile; @@ -81,6 +77,7 @@ import twilightforest.item.YetiArmorItem; import twilightforest.network.SyncQuestsPacket; import twilightforest.network.WipeOreMeterPacket; +import twilightforest.tags.TFEntityTypeTags; import twilightforest.util.datamaps.EntityTransformation; import twilightforest.util.entities.EntityUtil; import twilightforest.util.entities.OminousFireDamageSource; @@ -90,6 +87,7 @@ import twilightforest.world.components.structures.util.ControlledSpawns; import twilightforest.world.components.structures.util.ValidatedSpawnLocations; +import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -102,6 +100,7 @@ public class EntityEvents { private QuestingRamCurrentContext questingRamCurrentContext; private static final boolean SHIELD_PARRY_MOD_LOADED = ModList.get().isLoaded("parry"); + private static final EquipmentSlot[] ARMOR_SLOTS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; @PostConstruct private void setup() { @@ -133,13 +132,13 @@ private void ominousFireConversion(LivingDeathEvent event) { EntityTransformation dataMap = event.getEntity().getType().builtInRegistryHolder().getData(TFDataMaps.OMINOUS_FIRE); if (event.getEntity() instanceof ServerPlayer player) { - var zombie = EntityType.ZOMBIE.create(player.level()); + var zombie = EntityType.ZOMBIE.create(player.level(), EntitySpawnReason.CONVERSION); zombie.setData(TFDataAttachments.ZOMBIFIED_PLAYER, player.getGameProfile()); zombie.setCustomName(player.getName()); zombie.copyPosition(player); zombie.setCanPickUpLoot(true); zombie.setBaby(false); - EventHooks.finalizeMobSpawn(zombie, player.serverLevel(), player.level().getCurrentDifficultyAt(player.blockPosition()), EntitySpawnReason.CONVERSION, null); + EventHooks.finalizeMobSpawn(zombie, player.level(), player.level().getCurrentDifficultyAt(player.blockPosition()), EntitySpawnReason.CONVERSION, null); player.level().addFreshEntity(zombie); } else if (dataMap != null && event.getEntity().level() instanceof ServerLevel) { EntityUtil.convertEntity(event.getEntity(), dataMap.result()); @@ -157,7 +156,7 @@ private void zombifiedPlayerAttacks(LivingIncomingDamageEvent event) { private void alertPlayerCastleIsWIP(AdvancementEvent.AdvancementEarnEvent event) { if (event.getAdvancement().id().equals(TwilightForestMod.prefix("progression_end"))) { - event.getEntity().sendSystemMessage(Component.translatable("gui.twilightforest.progression_end.message", Component.translatable("gui.twilightforest.progression_end.discord").withStyle(style -> style.withColor(ChatFormatting.BLUE).applyFormat(ChatFormatting.UNDERLINE).withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://discord.experiment115.com/"))))); + event.getEntity().sendSystemMessage(Component.translatable("gui.twilightforest.progression_end.message", Component.translatable("gui.twilightforest.progression_end.discord").withStyle(style -> style.withColor(ChatFormatting.BLUE).applyFormat(ChatFormatting.UNDERLINE).withClickEvent(new ClickEvent.OpenUrl(URI.create("https://discord.experiment115.com/")))))); } } @@ -180,10 +179,17 @@ private void attachLeadToWroughtFence(PlayerInteractEvent.RightClickBlock event) private void wipeOreMeterOnLeftClick(PlayerInteractEvent.LeftClickEmpty event) { ItemStack item = event.getItemStack(); if (item.is(TFItems.ORE_METER.get()) && (item.has(TFDataComponents.ORE_DATA) || item.has(TFDataComponents.ORE_FILTER))) { - PacketDistributor.sendToServer(new WipeOreMeterPacket(event.getHand())); + ClientPacketDistributor.sendToServer(new WipeOreMeterPacket(event.getHand())); item.remove(TFDataComponents.ORE_DATA); item.remove(TFDataComponents.ORE_FILTER); - event.getLevel().playSound(event.getEntity(), event.getEntity().blockPosition(), TFSounds.ORE_METER_CLEAR.get(), SoundSource.PLAYERS, 1.25F, event.getLevel().getRandom().nextFloat() * 0.2F + 0.6F); + event.getLevel().playSound( + event.getEntity(), + event.getEntity().blockPosition(), + TFSounds.ORE_METER_CLEAR.get(), + SoundSource.PLAYERS, + 1.25F, + event.getLevel().getRandom().nextFloat() * 0.2F + 0.6F + ); } } @@ -198,7 +204,7 @@ private void entityHurts(LivingDamageEvent.Post event) { int chillLevel = getGearCoverage(living, true); if (fireLevel > 0 && living.getRandom().nextInt(25) < fireLevel && !trueSource.fireImmune()) { - trueSource.igniteForSeconds(fireLevel / 2); + trueSource.igniteForSeconds((float) fireLevel / 2); } if (trueSource instanceof LivingEntity target) { @@ -216,14 +222,14 @@ private void entityHurts(LivingDamageEvent.Post event) { } //if our casket is owned by someone and that player isnt the one breaking it, stop them - private void onCasketBreak(BlockEvent.BreakEvent event) { + private void onCasketBreak(BreakBlockEvent event) { Player player = event.getPlayer(); if (event.getState().getBlock() instanceof SkullChestBlock) { BlockEntity te = event.getLevel().getBlockEntity(event.getPos()); if (te instanceof SkullChestBlockEntity casket) { ResolvableProfile checker = casket.owner; if (checker != null && !casket.isEmpty()) { - if (!Commands.LEVEL_ADMINS.check(player.permissions()) || !player.getGameProfile().equals(checker.gameProfile())) { + if (!Commands.LEVEL_ADMINS.check(player.permissions()) || !player.getGameProfile().equals(checker.partialProfile())) { event.setCanceled(true); } } @@ -251,13 +257,13 @@ private void reduceFrostedEffectIfOnFire(LivingIncomingDamageEvent event) { private void onParryProjectile(ProjectileImpactEvent event) { final Projectile projectile = event.getProjectile(); - if (!projectile.getCommandSenderWorld().isClientSide() && !SHIELD_PARRY_MOD_LOADED && (TFConfig.parryNonTwilightAttacks || projectile instanceof ITFProjectile)) { + if (!projectile.level().isClientSide() && !SHIELD_PARRY_MOD_LOADED && (TFConfig.parryNonTwilightAttacks || projectile instanceof ITFProjectile)) { if (event.getRayTraceResult() instanceof EntityHitResult result) { Entity entity = result.getEntity(); if (entity instanceof LivingEntity entityBlocking) { if (entityBlocking.isBlocking() && entityBlocking.getUseItem().getUseDuration(entityBlocking) - entityBlocking.getUseItemRemainingTicks() <= TFConfig.shieldParryTicks) { - projectile.deflect(ProjectileDeflection.AIM_DEFLECT, entityBlocking, entityBlocking, true); + projectile.deflect(ProjectileDeflection.AIM_DEFLECT, entityBlocking, EntityReference.of(entityBlocking), true); event.setCanceled(true); } } @@ -323,8 +329,9 @@ private void createSkullCandle(PlayerInteractEvent.RightClickBlock event) { private static void makeSkullCandle(PlayerInteractEvent.RightClickBlock event, Block newBlock) { ResolvableProfile profile = null; Level level = event.getLevel(); - if (level.getBlockEntity(event.getPos()) instanceof SkullBlockEntity skull) + if (level.getBlockEntity(event.getPos()) instanceof SkullBlockEntity skull) { profile = skull.getOwnerProfile(); + } level.playSound(null, event.getPos(), SoundEvents.CANDLE_PLACE, SoundSource.BLOCKS, 1.0F, 1.0F); level.setBlockAndUpdate(event.getPos(), newBlock.withPropertiesOf(level.getBlockState(event.getPos())) .setValue(AbstractSkullCandleBlock.LIGHTING, LightableBlock.Lighting.NONE)); @@ -343,7 +350,8 @@ private static void makeSkullCandle(PlayerInteractEvent.RightClickBlock event, B public static int getGearCoverage(LivingEntity entity, boolean yeti) { int amount = 0; - for (ItemStack armor : entity.getArmorSlots()) { + for (EquipmentSlot armorSlot : ARMOR_SLOTS) { + ItemStack armor = entity.getItemBySlot(armorSlot); if (!armor.isEmpty() && (yeti ? armor.getItem() instanceof YetiArmorItem : armor.getItem() instanceof FieryArmorItem)) { amount++; } @@ -429,7 +437,7 @@ private void removeCastleTextIfAttacked(AttackEntityEvent event) { // For clearing our Display text entities at the Final Castle Gazebo, there's no other way to remove them otherwise // The tag distinguishes our Interaction entities from other Mods' utilization if (event.getTarget().level() instanceof ServerLevel level && event.getTarget() instanceof Interaction interaction - && interaction.getTags().contains(FinalCastleBossGazeboComponent.INTERACTION_TAG)) { + && interaction.entityTags().contains(FinalCastleBossGazeboComponent.INTERACTION_TAG)) { AABB bounds = interaction.getBoundingBox(); level.getEntities(interaction, bounds, e -> e instanceof Display).forEach(Entity::discard); interaction.discard(); @@ -507,29 +515,51 @@ private void handleLeashPathingOverrides(EntityJoinLevelEvent event) { private void stopEndermenFromGrabbingBlocksInTF(EntityJoinLevelEvent event) { if (event.getEntity() instanceof EnderMan enderMan) { enderMan.goalSelector.getAvailableGoals().stream() - .filter(g -> g.getGoal() instanceof EnderMan.EndermanTakeBlockGoal) + .filter(g -> g.getGoal().getClass().getName().endsWith("EndermanTakeBlockGoal")) .findAny() .ifPresent(g -> { enderMan.goalSelector.removeGoal(g.getGoal()); - enderMan.goalSelector.addGoal(g.getPriority(), new ExtendedEndermanTakeBlockGoal((EnderMan.EndermanTakeBlockGoal) g.getGoal(), enderMan)); + enderMan.goalSelector.addGoal(g.getPriority(), new ExtendedEndermanTakeBlockGoal(g.getGoal(), enderMan)); }); } } - static class ExtendedEndermanTakeBlockGoal extends EnderMan.EndermanTakeBlockGoal { - - private final EnderMan.EndermanTakeBlockGoal delegate; + static class ExtendedEndermanTakeBlockGoal extends Goal { + private final Goal delegate; private final EnderMan enderman; - public ExtendedEndermanTakeBlockGoal(EnderMan.EndermanTakeBlockGoal delegate, EnderMan enderman) { - super(enderman); + public ExtendedEndermanTakeBlockGoal(Goal delegate, EnderMan enderman) { this.delegate = delegate; this.enderman = enderman; + this.setFlags(delegate.getFlags()); } @Override public boolean canUse() { - return this.delegate.canUse() && !this.enderman.level().dimensionTypeRegistration().is(TFDimensionData.TWILIGHT_DIM_TYPE); + if (this.enderman.level().dimensionTypeRegistration().is(TFDimensionData.TWILIGHT_DIM_TYPE)) { + return false; + } + return this.delegate.canUse(); + } + + @Override + public boolean canContinueToUse() { + return this.delegate.canContinueToUse(); + } + + @Override + public boolean isInterruptable() { + return this.delegate.isInterruptable(); + } + + @Override + public void start() { + this.delegate.start(); + } + + @Override + public void stop() { + this.delegate.stop(); } @Override diff --git a/src/main/java/twilightforest/events/MiscEvents.java b/src/main/java/twilightforest/events/MiscEvents.java index 224fe77dd3..8a955e8690 100644 --- a/src/main/java/twilightforest/events/MiscEvents.java +++ b/src/main/java/twilightforest/events/MiscEvents.java @@ -91,7 +91,7 @@ private void addTomesToLecterns(PlayerInteractEvent.RightClickBlock event) { Player player = event.getEntity(); ItemStack stack = player.getItemInHand(event.getHand()); - if (!(stack.getItem() instanceof SpawnEggItem spawnEggItem) || spawnEggItem.getType(stack) != TFEntities.DEATH_TOME.get()) + if (!(stack.getItem() instanceof SpawnEggItem) || SpawnEggItem.getType(stack) != TFEntities.DEATH_TOME.get()) return; BlockPos pos = event.getPos(); @@ -103,7 +103,7 @@ private void addTomesToLecterns(PlayerInteractEvent.RightClickBlock event) { level.playSound(null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F); if (level instanceof ServerLevel serverLevel) { - DeathTome tome = TFEntities.DEATH_TOME.get().spawn(serverLevel, stack, player, pos.below(), EntitySpawnReason.SPAWN_EGG, true, false); + DeathTome tome = TFEntities.DEATH_TOME.get().spawn(serverLevel, stack, player, pos.below(), EntitySpawnReason.SPAWN_ITEM_USE, true, false); if (tome != null) { stack.consume(1, player); serverLevel.gameEvent(player, GameEvent.ENTITY_PLACE, pos); diff --git a/src/main/java/twilightforest/events/ProgressionEvents.java b/src/main/java/twilightforest/events/ProgressionEvents.java index 3b991f6753..d8f001408d 100644 --- a/src/main/java/twilightforest/events/ProgressionEvents.java +++ b/src/main/java/twilightforest/events/ProgressionEvents.java @@ -31,6 +31,7 @@ import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.level.BlockEvent; import net.neoforged.neoforge.event.level.GameRuleChangedEvent; +import net.neoforged.neoforge.event.level.block.BreakBlockEvent; import net.neoforged.neoforge.event.tick.PlayerTickEvent; import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.server.ServerLifecycleHooks; @@ -90,7 +91,7 @@ private void gameRuleChanged(GameRuleChangedEvent event) { /** * Check if the player is trying to break a block in a structure that's considered unbreakable for progression reasons */ - private void preventLockedAreaBlockBreaking(BlockEvent.BreakEvent event) { + private void preventLockedAreaBlockBreaking(BreakBlockEvent event) { if (!(event.getLevel() instanceof ServerLevel level) || event.isCanceled()) return; BlockPos pos = event.getPos(); @@ -264,7 +265,7 @@ private static void checkForPortalCreation(ServerPlayer player, ServerLevel leve if (!TFPortalBlock.isPlayerNotifiedOfRequirement(player)) { // .doesPlayerHaveRequiredAdvancement null-checks already, so we can skip null-checking the `requirement` DisplayInfo info = requirement.value().display().orElse(null); - PacketDistributor.sendToPlayer(player, info == null ? new MissingAdvancementToastPacket(net.minecraft.network.chat.Component.translatable("twilightforest.ui.advancement.no_title"), new ItemStack(TFBlocks.TWILIGHT_PORTAL_MINIATURE_STRUCTURE.get())) : new MissingAdvancementToastPacket(info.getTitle(), info.getIcon())); + PacketDistributor.sendToPlayer(player, info == null ? new MissingAdvancementToastPacket(net.minecraft.network.chat.Component.translatable("twilightforest.ui.advancement.no_title"), new ItemStack(TFBlocks.TWILIGHT_PORTAL_MINIATURE_STRUCTURE.get())) : new MissingAdvancementToastPacket(info.getTitle(), info.getIcon().create())); TFPortalBlock.playerNotifiedOfRequirement(player); } @@ -279,7 +280,7 @@ private static void checkForPortalCreation(ServerPlayer player, ServerLevel leve double vy = rand.nextGaussian() * 0.02D; double vz = rand.nextGaussian() * 0.02D; - level.addParticle(ParticleTypes.EFFECT, qualified.getX(), qualified.getY() + 0.2, qualified.getZ(), vx, vy, vz); + level.addParticle(() -> ParticleTypes.EFFECT, qualified.getX(), qualified.getY() + 0.2, qualified.getZ(), vx, vy, vz); } if (TFBlocks.TWILIGHT_PORTAL.get().tryToCreatePortal(level, qualified.blockPosition(), qualified, player)) diff --git a/src/main/java/twilightforest/events/RegistrationEvents.java b/src/main/java/twilightforest/events/RegistrationEvents.java index 1dd682033e..771553cff1 100644 --- a/src/main/java/twilightforest/events/RegistrationEvents.java +++ b/src/main/java/twilightforest/events/RegistrationEvents.java @@ -3,17 +3,16 @@ import com.google.common.collect.Maps; import net.minecraft.core.Direction; import net.minecraft.core.Registry; -import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.SpawnPlacementTypes; import net.minecraft.world.entity.animal.Animal; -import net.minecraft.world.entity.animal.Sheep; -import net.minecraft.world.entity.monster.AbstractSkeleton; +import net.minecraft.world.entity.animal.sheep.Sheep; import net.minecraft.world.entity.monster.Monster; -import net.minecraft.world.entity.monster.Spider; -import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.monster.skeleton.AbstractSkeleton; +import net.minecraft.world.entity.monster.spider.Spider; +import net.minecraft.world.entity.monster.zombie.Zombie; import net.minecraft.world.item.AxeItem; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; @@ -221,8 +220,8 @@ public void setupPackets(RegisterPayloadHandlersEvent event) { registrar.playToClient(MissingAdvancementToastPacket.TYPE, MissingAdvancementToastPacket.STREAM_CODEC, MissingAdvancementToastPacket::handle); registrar.playToClient(MovePlayerPacket.TYPE, MovePlayerPacket.STREAM_CODEC, MovePlayerPacket::handle); registrar.playToClient(ParticlePacket.TYPE, ParticlePacket.STREAM_CODEC, ParticlePacket::handle); - registrar.playBidirectional(GogglesZoomPacket.TYPE, GogglesZoomPacket.STREAM_CODEC, GogglesZoomPacket::handle); - registrar.playBidirectional(GradualGlidePacket.TYPE, GradualGlidePacket.STREAM_CODEC, GradualGlidePacket::handle); + registrar.playToServer(GogglesZoomPacket.TYPE, GogglesZoomPacket.STREAM_CODEC, GogglesZoomPacket::handle); + registrar.playBidirectional(GradualGlidePacket.TYPE, GradualGlidePacket.STREAM_CODEC, GradualGlidePacket::handle, GradualGlidePacket::handle); registrar.playToServer(PerformDoubleJumpPacket.TYPE, PerformDoubleJumpPacket.STREAM_CODEC, PerformDoubleJumpPacket::handle); registrar.playToServer(SwapHotbarPacket.TYPE, SwapHotbarPacket.STREAM_CODEC, SwapHotbarPacket::handle); registrar.playToServer(PerformSidestepPacket.TYPE, PerformSidestepPacket.STREAM_CODEC, PerformSidestepPacket::handle); @@ -249,10 +248,11 @@ public void init(FMLCommonSetupEvent evt) { TFDispenserBehaviors.init(); TFStats.init(); - CauldronInteraction.WATER.map().put(TFItems.ARCTIC_HELMET.get(), CauldronInteraction.DYED_ITEM); - CauldronInteraction.WATER.map().put(TFItems.ARCTIC_CHESTPLATE.get(), CauldronInteraction.DYED_ITEM); - CauldronInteraction.WATER.map().put(TFItems.ARCTIC_LEGGINGS.get(), CauldronInteraction.DYED_ITEM); - CauldronInteraction.WATER.map().put(TFItems.ARCTIC_BOOTS.get(), CauldronInteraction.DYED_ITEM); + // No analogs in 26.1.x +// CauldronInteractions.WATER.map().put(TFItems.ARCTIC_HELMET.get(), CauldronInteractions.DYED_ITEM); +// CauldronInteractions.WATER.map().put(TFItems.ARCTIC_CHESTPLATE.get(), CauldronInteractions.DYED_ITEM); +// CauldronInteractions.WATER.map().put(TFItems.ARCTIC_LEGGINGS.get(), CauldronInteractions.DYED_ITEM); +// CauldronInteractions.WATER.map().put(TFItems.ARCTIC_BOOTS.get(), CauldronInteractions.DYED_ITEM); AxeItem.STRIPPABLES = Maps.newHashMap(AxeItem.STRIPPABLES); AxeItem.STRIPPABLES.put(TFBlocks.TWILIGHT_OAK_LOG.get(), TFBlocks.STRIPPED_TWILIGHT_OAK_LOG.get()); diff --git a/src/main/java/twilightforest/events/ToolEvents.java b/src/main/java/twilightforest/events/ToolEvents.java index 1ac62fc537..a019bf4eea 100644 --- a/src/main/java/twilightforest/events/ToolEvents.java +++ b/src/main/java/twilightforest/events/ToolEvents.java @@ -1,6 +1,7 @@ package twilightforest.events; import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.game.ClientboundAnimatePacket; @@ -34,16 +35,17 @@ import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent; import net.neoforged.neoforge.event.entity.living.MobEffectEvent; import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.event.level.block.BreakBlockEvent; import org.jetbrains.annotations.Nullable; import tamaized.beanification.Component; import tamaized.beanification.PostConstruct; import twilightforest.block.GiantBlock; import twilightforest.components.entity.GiantPickaxeMiningAttachment; -import twilightforest.tags.TFBlockTags; import twilightforest.init.TFDataAttachments; import twilightforest.init.TFItems; import twilightforest.item.*; import twilightforest.loot.modifiers.GiantToolGroupingModifier; +import twilightforest.tags.TFBlockTags; import java.util.List; @@ -82,7 +84,7 @@ private void onEnderBowHit(ProjectileImpactEvent evt) { player.invulnerableTime = 40; player.level().broadcastEntityEvent(player, (byte) 46); if (living.isPassenger() && living.getVehicle() != null) { - player.startRiding(living.getVehicle(), true); + player.startRiding(living.getVehicle(), true, false); living.stopRiding(); } player.playSound(SoundEvents.CHORUS_FRUIT_TELEPORT, 1.0F, 1.0F); @@ -92,7 +94,7 @@ private void onEnderBowHit(ProjectileImpactEvent evt) { living.teleportTo(sourceX, sourceY, sourceZ); living.level().broadcastEntityEvent(player, (byte) 46); if (playerVehicle != null) { - living.startRiding(playerVehicle, true); + living.startRiding(playerVehicle, true, false); player.stopRiding(); } living.playSound(SoundEvents.CHORUS_FRUIT_TELEPORT, 1.0F, 1.0F); @@ -123,11 +125,11 @@ private void doKnightmetalToolLogic(LivingIncomingDamageEvent event) { container.setNewDamage(container.getNewDamage() + KNIGHTMETAL_BONUS_DAMAGE); } // enchantment attack sparkles - ((ServerLevel) target.level()).getChunkSource().broadcastAndSend(target, new ClientboundAnimatePacket(target, 5)); + ((ServerLevel) target.level()).getChunkSource().sendToTrackingPlayers(target, new ClientboundAnimatePacket(target, 5)); } else if (target.getArmorValue() == 0 && weapon.is(TFItems.KNIGHTMETAL_AXE.get())) { container.setNewDamage(container.getOriginalDamage() + KNIGHTMETAL_BONUS_DAMAGE); // enchantment attack sparkles - ((ServerLevel) target.level()).getChunkSource().broadcastAndSend(target, new ClientboundAnimatePacket(target, 5)); + ((ServerLevel) target.level()).getChunkSource().sendToTrackingPlayers(target, new ClientboundAnimatePacket(target, 5)); } } } @@ -143,13 +145,13 @@ private void addExtraAxeChargingDamage(LivingIncomingDamageEvent event) { if (!weapon.isEmpty() && weapon.getItem() instanceof MinotaurAxeItem) { container.setNewDamage(container.getNewDamage() + MINOTAUR_AXE_BONUS_DAMAGE); // enchantment attack sparkles - ((ServerLevel) target.level()).getChunkSource().broadcastAndSend(target, new ClientboundAnimatePacket(target, 5)); + ((ServerLevel) target.level()).getChunkSource().sendToTrackingPlayers(target, new ClientboundAnimatePacket(target, 5)); } } } } - private void damageNonMazebreakerToolsMore(BlockEvent.BreakEvent event) { + private void damageNonMazebreakerToolsMore(BreakBlockEvent event) { ItemStack stack = event.getPlayer().getMainHandItem(); if (event.getState().is(TFBlockTags.MAZEBREAKER_ACCELERATED)) { if (stack.isDamageableItem() && !(stack.getItem() instanceof MazebreakerPickItem)) { @@ -159,12 +161,12 @@ private void damageNonMazebreakerToolsMore(BlockEvent.BreakEvent event) { } private void preventFatigueWithPocketWatch(MobEffectEvent.Applicable event) { - if (event.getApplicationResult() && event.getEffectInstance().is(MobEffects.DIG_SLOWDOWN) && event.getEntity().isHolding(TFItems.POCKET_WATCH.get())) { + if (event.getApplicationResult() && event.getEffectInstance().is(MobEffects.MINING_FATIGUE) && event.getEntity().isHolding(TFItems.POCKET_WATCH.get())) { event.setResult(MobEffectEvent.Applicable.Result.DO_NOT_APPLY); } } - private void handleGiantPickaxeMining(BlockEvent.BreakEvent event) { + private void handleGiantPickaxeMining(BreakBlockEvent event) { BlockPos pos = event.getPos(); BlockState state = event.getState(); @@ -174,7 +176,7 @@ private void handleGiantPickaxeMining(BlockEvent.BreakEvent event) { if (shouldBreakGiantBlock(player, attachment)) { attachment.setBreaking(true); // Tell the capability that a block breaking loop is happening, so it knows to fail the if check above. Otherwise, this would go on forever - LootParams.Builder builder = new LootParams.Builder(player.serverLevel()) + LootParams.Builder builder = new LootParams.Builder(player.level().getLevel()) .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) .withParameter(LootContextParams.BLOCK_STATE, state) .withOptionalParameter(LootContextParams.THIS_ENTITY, player) @@ -224,13 +226,13 @@ private void refreshOreMagnetCache(TagsUpdatedEvent event) { OreMagnetItem.TREE_ORE_TO_BLOCK_REPLACEMENTS.clear(); //collect all tags - for (TagKey tag : BuiltInRegistries.BLOCK.getTagNames().filter(location -> location.location().getNamespace().equals("c")).toList()) { + for (TagKey tag : BuiltInRegistries.BLOCK.getTags().filter(location -> location.key().location().getNamespace().equals("c")).map(HolderSet.Named::key).toList()) { //check if the tag is a valid ore tag if (tag.location().getPath().contains("ores_in_ground/")) { //grab the part after the slash for use later String oreground = tag.location().getPath().substring(15); //check if a tag for ore grounds matches up with our ores in ground tag - if (BuiltInRegistries.BLOCK.getTagNames().filter(location -> location.location().getNamespace().equals("c")).anyMatch(blockTagKey -> blockTagKey.location().getPath().equals("ore_bearing_ground/" + oreground))) { + if (BuiltInRegistries.BLOCK.getTags().filter(location -> location.key().location().getNamespace().equals("c")).anyMatch(blockTagKey -> blockTagKey.key().location().getPath().equals("ore_bearing_ground/" + oreground))) { //add each ground type to each ore BuiltInRegistries.BLOCK.get(TagKey.create(Registries.BLOCK, Identifier.fromNamespaceAndPath("c", "ore_bearing_ground/" + oreground))).get().forEach(ground -> BuiltInRegistries.BLOCK.get(tag).get().forEach(ore -> { diff --git a/src/main/java/twilightforest/events/TravellersGearEvents.java b/src/main/java/twilightforest/events/TravellersGearEvents.java index c71e37b8d7..60ce9ca1b4 100644 --- a/src/main/java/twilightforest/events/TravellersGearEvents.java +++ b/src/main/java/twilightforest/events/TravellersGearEvents.java @@ -8,7 +8,6 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; @@ -18,8 +17,8 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ItemAttributeModifiers; import net.minecraft.world.item.component.ItemContainerContents; @@ -278,7 +277,7 @@ private void stopDamagingTravellersGear(ArmorHurtEvent event) { if (damagedStack.getDamageValue() + event.getNewDamage(slot) >= damagedStack.getMaxDamage()) { event.setNewDamage(slot, damagedStack.getMaxDamage() - damagedStack.getDamageValue() - 1); } else if (damagedStack.getDamageValue() + event.getNewDamage(slot) >= damagedStack.getMaxDamage() - 1 && event.getEntity() instanceof ServerPlayer player) { - player.level().playLocalSound(player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_BREAK.value(), SoundSource.PLAYERS, 1.0F, player.getVoicePitch(), false); + player.playSound(SoundEvents.ITEM_BREAK.value(), 1.0F, player.getVoicePitch()); } }); } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 38538af1b6..54762d2621 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -116,7 +116,7 @@ public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData trackedDecora # TFOverlays (partially determines if the quest ram indicator should render below the crosshair, and allows the food bar to be rendered when riding hostile mounts) public net.minecraft.client.gui.Gui canRenderCrosshairForSpectator(Lnet/minecraft/world/phys/HitResult;)Z -#public net.minecraft.client.gui.Gui renderFood(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/entity/player/Player;II)V +public net.minecraft.client.gui.Gui extractFood(Lnet/minecraft/client/gui/GuiGraphicsExtractor;Lnet/minecraft/world/entity/player/Player;II)V # TFSkyRenderer (allows for rendering the sky) public net.minecraft.client.renderer.LevelRenderer skyRenderer