Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fb4c73d
Events and hooks port
albazavr-alba Jun 24, 2026
c1de065
Removed every @NotNull and unnecessary line change
albazavr-alba Jul 5, 2026
8ee5f57
Merge branch 'latest' into port-events-and-hooks
albazavr-alba Jul 13, 2026
72a945a
Fixed files
albazavr-alba Jul 15, 2026
aad53bd
Fixed review comment for EntityHooks
albazavr-alba Jul 20, 2026
dc54f61
Fixed ClientGameEvents
albazavr-alba Jul 21, 2026
1d6b091
Fixed ClientRegistrationEvents
albazavr-alba Jul 23, 2026
148624a
Fixed ClientRegistrationEvents
albazavr-alba Jul 23, 2026
bb8ed59
Excluded CloudEvents
albazavr-alba Jul 23, 2026
7f18e76
Fixed OverlayHandler
albazavr-alba Jul 23, 2026
bfce2b6
Fixed TravellersClientEvents
albazavr-alba Jul 23, 2026
3f552eb
Fixed CapabilityEvents.java
albazavr-alba Jul 23, 2026
bc3d093
Merge branch 'latest' into port-events-and-hooks
albazavr-alba Jul 24, 2026
782d0f9
Fixed CharmEvents
albazavr-alba Jul 24, 2026
79807a5
Merge remote-tracking branch 'origin/port-events-and-hooks' into port…
albazavr-alba Jul 24, 2026
6cd6dac
Fixed CapabilityEvents
albazavr-alba Jul 24, 2026
147d3a9
Fixed ProgressionEvents
albazavr-alba Jul 24, 2026
c34a2a8
Fixed CapabilityEvents
albazavr-alba Jul 24, 2026
dcec00e
Fixed EntityEvents
albazavr-alba Jul 24, 2026
87773d2
Fixed CharmEvents
albazavr-alba Jul 24, 2026
6a97e5b
Fixed ProgressionEvents
albazavr-alba Jul 24, 2026
d662f9a
Fixed RegistrationEvents
albazavr-alba Jul 24, 2026
dadbddd
Fixed ToolEvents
albazavr-alba Jul 24, 2026
7bf3324
Fixed FogHandler
albazavr-alba Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/main/java/twilightforest/asmhooks/EntityHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,7 +25,6 @@ public class EntityHooks {
* Injection Point:<br/>
* {@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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -99,9 +98,9 @@ public static float resetFactorWithUnrestrained(float o, Entity entity) {
* {@link net.minecraft.world.entity.Entity#move(MoverType, Vec3)}<br/>
*/
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;
}
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/twilightforest/asmhooks/MultipartHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -39,7 +37,7 @@ public static Iterator<Entity> resolveEntitiesForRendering(Iterator<Entity> 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);
}

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/twilightforest/asmhooks/PlayerHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
129 changes: 79 additions & 50 deletions src/main/java/twilightforest/client/event/ClientGameEvents.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
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.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShapeRenderer;
import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
Expand All @@ -21,6 +21,8 @@
import net.minecraft.sounds.Music;
import net.minecraft.sounds.Musics;
import net.minecraft.util.Mth;
import net.minecraft.world.attribute.BackgroundMusic;
import net.minecraft.world.attribute.EnvironmentAttributes;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
Expand All @@ -35,6 +37,7 @@
import net.minecraft.world.phys.shapes.VoxelShape;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModList;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.client.gui.VanillaGuiLayers;
import net.neoforged.neoforge.common.NeoForge;
Expand All @@ -50,13 +53,15 @@
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.awt.*;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.Month;
import java.util.HashSet;
Expand All @@ -77,6 +82,8 @@ public class ClientGameEvents {
private int aurora = 0;
private int lastAurora = 0;

private static Field skyFlashTimeField;

@Autowired(dist = Dist.CLIENT)
private HolderMatcher holderMatcher;

Expand Down Expand Up @@ -139,7 +146,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));
}
}

Expand All @@ -157,30 +164,33 @@ 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) {
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder buffer = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
if (aurora > 0 || lastAurora > 0) {
var bufferSource = Minecraft.getInstance().renderBuffers().bufferSource();

VertexConsumer consumer = bufferSource.getBuffer(TFShaders.AURORA);

float partialTicks = Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaTicks();
float alpha = (Mth.lerp(partialTicks, lastAurora, aurora)) / 60F * 0.5F;

final float scale = 2048F * (Minecraft.getInstance().gameRenderer.getRenderDistance() / 32F);
Vec3 pos = event.getCamera().getPosition();
final float scale = 2048F * (Minecraft.getInstance().options.renderDistance().get() / 32F);
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();

PoseStack poseStack = event.getPoseStack();
poseStack.pushPose();

PoseStack.Pose lastPose = poseStack.last();

consumer.addVertex(lastPose.pose(), -scale, y, scale).setColor(1F, 1F, 1F, alpha);
consumer.addVertex(lastPose.pose(), -scale, y, -scale).setColor(1F, 1F, 1F, alpha);
consumer.addVertex(lastPose.pose(), scale, y, -scale).setColor(1F, 1F, 1F, alpha);
consumer.addVertex(lastPose.pose(), scale, y, scale).setColor(1F, 1F, 1F, alpha);

poseStack.popPose();
bufferSource.endBatch(TFShaders.AURORA);
}
}

Expand All @@ -203,9 +213,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> biome = mc.level.getBiome(mc.cameraEntity.blockPosition());
Holder<Biome> biome = mc.level.getBiome(mc.getCameraEntity().blockPosition());
if (TFConfig.getValidAuroraBiomes(access).stream().anyMatch(c -> holderMatcher.match(c, biome)))
aurora++;
else
Expand All @@ -218,7 +228,9 @@ private void clientTick(ClientTickEvent.Post event) {
BugModelAnimationHelper.animate();

if (mc.level != null) {
if (mc.level.getSkyFlashTime() > 0) {
Integer flashTime = ObfuscationReflectionHelper.getPrivateValue(ClientLevel.class, mc.level, "skyFlashTime");

if (flashTime != null && flashTime > 0) {
MagicPaintingRenderer.lastLightning = mc.level.getGameTime();
}

Expand All @@ -239,7 +251,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.absSnapTo(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;
Expand Down Expand Up @@ -289,12 +301,16 @@ 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;
private void unrenderHeadWithTrophies(RenderLivingEvent.Pre<?, ?, ?> event) {
LocalPlayer localPlayer = Minecraft.getInstance().player;
if (localPlayer == null) {
return;
}
ItemStack stack = localPlayer.getItemBySlot(EquipmentSlot.HEAD);
boolean visible = !(stack.is(TFItemTags.TROPHIES)) && !areCuriosEquipped(localPlayer);
boolean isPlayer = true;
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
Comment thread
albazavr-alba marked this conversation as resolved.
headedModel.getHead().visible = visible && (!isPlayer || headedModel.getHead().visible);
if (event.getRenderer().getModel() instanceof HumanoidModel<?> humanoidModel) {
humanoidModel.hat.visible = visible && (!isPlayer || humanoidModel.hat.visible);
}
Expand All @@ -303,7 +319,7 @@ private void unrenderHeadWithTrophies(RenderLivingEvent.Pre<?, ?> event) {

private boolean areCuriosEquipped(LivingEntity entity) {
if (ModList.get().isLoaded("curios")) {
return CuriosCompat.isCurioEquippedAndVisible(entity, stack -> stack.getItem() instanceof TrophyItem);
return CuriosCompat.isCurioEquippedAndVisible(entity, stack -> stack.is(TFItemTags.TROPHIES));
}
return false;
}
Expand All @@ -323,24 +339,37 @@ private void translateBookAuthor(ItemTooltipEvent event) {
}
}

private void renderGiantBlockOutlines(RenderHighlightEvent.Block event) {
BlockPos pos = event.getTarget().getBlockPos();
BlockState state = event.getCamera().getEntity().level().getBlockState(pos);
private void renderGiantBlockOutlines(ExtractBlockOutlineRenderStateEvent event) {
BlockPos pos = event.getBlockPos();
BlockState state = event.getBlockState();

if (state.getBlock() instanceof MiniatureStructureBlock) {
Comment thread
albazavr-alba marked this conversation as resolved.
event.setCanceled(true);
return;
}
boolean isMiniature = state.getBlock() instanceof MiniatureStructureBlock;

LocalPlayer player = Minecraft.getInstance().player;
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);
}
boolean isHoldingGiantTool = player != null && (player.getMainHandItem().getItem() instanceof GiantPickItem
|| (player.getMainHandItem().getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof GiantBlock));

if (isMiniature || (isHoldingGiantTool && !state.isAir() && player.level().getWorldBorder().isWithinBounds(pos))) {
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().position();
BlockPos offsetPos = new BlockPos(pos.getX() & ~0b11, pos.getY() & ~0b11, pos.getZ() & ~0b11);
Vec3 xyz = Vec3.atLowerCornerOf(offsetPos).subtract(cameraPos);

int outlineColor = 0x7F000000;
event.addCustomRenderer((_, bufferSource, poseStack, _, _) -> {

if (isHoldingGiantTool && !isMiniature) {
VertexConsumer consumer = bufferSource.getBuffer(RenderTypes.lines());
ShapeRenderer.renderShape(
poseStack,
consumer,
GIANT_BLOCK,
xyz.x(), xyz.y(), xyz.z(),
outlineColor, 1.0F
);
}

return false;
});
}
}

Expand Down
Loading