getTagSearchKeys() {
return tagSearchKeys;
}
- @Nullable
- public static SessionSearchTrees.Key getNameSearchKey(CreativeModeTab tab) {
+ public static SessionSearchTrees.@Nullable Key getNameSearchKey(CreativeModeTab tab) {
if (tab == CreativeModeTabs.searchTab())
return SessionSearchTrees.CREATIVE_NAMES;
@@ -62,8 +61,7 @@ public static SessionSearchTrees.Key getNameSearchKey(CreativeModeTab tab) {
return NAME_SEARCH_KEYS.computeIfAbsent(tab, k -> new SessionSearchTrees.Key());
}
- @Nullable
- public static SessionSearchTrees.Key getTagSearchKey(CreativeModeTab tab) {
+ public static SessionSearchTrees.@Nullable Key getTagSearchKey(CreativeModeTab tab) {
if (tab == CreativeModeTabs.searchTab())
return SessionSearchTrees.CREATIVE_TAGS;
diff --git a/src/client/java/net/neoforged/neoforge/client/CustomCloudsRenderer.java b/src/client/java/net/neoforged/neoforge/client/CustomCloudsRenderer.java
new file mode 100644
index 00000000000..f3223bd4ee6
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/CustomCloudsRenderer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client;
+
+import net.minecraft.client.CloudStatus;
+import net.minecraft.client.renderer.state.LevelRenderState;
+import net.minecraft.world.phys.Vec3;
+import net.neoforged.neoforge.client.event.ExtractLevelRenderStateEvent;
+import net.neoforged.neoforge.client.event.RegisterCustomEnvironmentEffectRendererEvent;
+import org.joml.Matrix4f;
+
+/**
+ * A custom cloud renderer that can be registered using {@link RegisterCustomEnvironmentEffectRendererEvent#registerCloudRenderer)}
+ * and used with {@link net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_CLOUDS}.
+ *
+ * Custom render state needed for the various render methods must be extracted via {@link ExtractLevelRenderStateEvent}
+ * and stored in the provided {@link LevelRenderState}.
+ *
+ * @see RegisterCustomEnvironmentEffectRendererEvent#registerCloudRenderer
+ * @see net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_CLOUDS
+ */
+public interface CustomCloudsRenderer {
+ /**
+ * Renders the clouds of this dimension.
+ *
+ * @return true to prevent vanilla cloud rendering
+ */
+ default boolean renderClouds(LevelRenderState levelRenderState, Vec3 camPos, CloudStatus cloudStatus, int cloudColor, float cloudHeight, Matrix4f modelViewMatrix) {
+ return false;
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/CustomEnvironmentEffectsRendererManager.java b/src/client/java/net/neoforged/neoforge/client/CustomEnvironmentEffectsRendererManager.java
new file mode 100644
index 00000000000..e9730aac0a9
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/CustomEnvironmentEffectsRendererManager.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) Forge Development LLC and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import net.minecraft.resources.Identifier;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.phys.Vec3;
+import net.neoforged.fml.ModLoader;
+import net.neoforged.neoforge.client.event.RegisterCustomEnvironmentEffectRendererEvent;
+import net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Manager for custom renderers referred to by {@link net.minecraft.world.attribute.EnvironmentAttribute}.
+ */
+public final class CustomEnvironmentEffectsRendererManager {
+ private static @Nullable Map CUSTOM_CLOUD_RENDERERS;
+ private static @Nullable Map CUSTOM_SKYBOX_RENDERERS;
+ private static @Nullable Map CUSTOM_WEATHER_EFFECT_RENDERERS;
+
+ /**
+ * Finds the {@link CustomCloudsRenderer} for a given identifier, or null if none is registered.
+ */
+ public static @Nullable CustomCloudsRenderer getCustomCloudsRenderer(Identifier id) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_CLOUDS.equals(id)) {
+ return null;
+ }
+ return Objects.requireNonNull(CUSTOM_CLOUD_RENDERERS).get(id);
+ }
+
+ /**
+ * Finds the {@link CustomCloudsRenderer} to use for the given position in the given level.
+ */
+ public static @Nullable CustomCloudsRenderer getCustomCloudsRenderer(Level level, Vec3 position) {
+ var id = level.environmentAttributes().getValue(NeoForgeEnvironmentAttributes.CUSTOM_CLOUDS, position);
+ return getCustomCloudsRenderer(id);
+ }
+
+ /**
+ * Finds the {@link CustomSkyboxRenderer} for a given identifier, or null if none is registered.
+ */
+ public static @Nullable CustomSkyboxRenderer getCustomSkyboxRenderer(Identifier id) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_SKYBOX.equals(id)) {
+ return null;
+ }
+ return Objects.requireNonNull(CUSTOM_SKYBOX_RENDERERS).get(id);
+ }
+
+ /**
+ * Finds the {@link CustomSkyboxRenderer} to use for the given position in the given level.
+ */
+ public static @Nullable CustomSkyboxRenderer getCustomSkyboxRenderer(Level level, Vec3 position) {
+ var id = level.environmentAttributes().getValue(NeoForgeEnvironmentAttributes.CUSTOM_SKYBOX, position);
+ return getCustomSkyboxRenderer(id);
+ }
+
+ /**
+ * Finds the {@link CustomWeatherEffectRenderer} for a given identifier, or null if none is registered.
+ */
+ public static @Nullable CustomWeatherEffectRenderer getCustomWeatherEffectRenderer(Identifier id) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_WEATHER_EFFECTS.equals(id)) {
+ return null;
+ }
+ return Objects.requireNonNull(CUSTOM_WEATHER_EFFECT_RENDERERS).get(id);
+ }
+
+ /**
+ * Finds the {@link CustomWeatherEffectRenderer} to use for the given position in the given level.
+ */
+ public static @Nullable CustomWeatherEffectRenderer getCustomWeatherEffectRenderer(Level level, Vec3 position) {
+ var id = level.environmentAttributes().getValue(NeoForgeEnvironmentAttributes.CUSTOM_WEATHER_EFFECTS, position);
+ return getCustomWeatherEffectRenderer(id);
+ }
+
+ @ApiStatus.Internal
+ public static void init() {
+ if (CUSTOM_CLOUD_RENDERERS != null) {
+ throw new IllegalStateException("Already initialized.");
+ }
+
+ var customCloudRenderers = new HashMap();
+ var customSkyboxRenderers = new HashMap();
+ var customWeatherEffectRenderers = new HashMap();
+ ModLoader.postEventWrapContainerInModOrder(new RegisterCustomEnvironmentEffectRendererEvent(customCloudRenderers, customSkyboxRenderers, customWeatherEffectRenderers));
+ CUSTOM_CLOUD_RENDERERS = Map.copyOf(customCloudRenderers);
+ CUSTOM_SKYBOX_RENDERERS = Map.copyOf(customSkyboxRenderers);
+ CUSTOM_WEATHER_EFFECT_RENDERERS = Map.copyOf(customWeatherEffectRenderers);
+ }
+
+ private CustomEnvironmentEffectsRendererManager() {}
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/CustomSkyboxRenderer.java b/src/client/java/net/neoforged/neoforge/client/CustomSkyboxRenderer.java
new file mode 100644
index 00000000000..3ff0546a790
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/CustomSkyboxRenderer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client;
+
+import net.minecraft.client.renderer.state.LevelRenderState;
+import net.minecraft.client.renderer.state.SkyRenderState;
+import net.neoforged.neoforge.client.event.ExtractLevelRenderStateEvent;
+import net.neoforged.neoforge.client.event.RegisterCustomEnvironmentEffectRendererEvent;
+import org.joml.Matrix4f;
+
+/**
+ * A custom skybox renderer that can be registered using {@link RegisterCustomEnvironmentEffectRendererEvent#registerSkyboxRenderer}
+ * and used with {@link net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_SKYBOX}.
+ *
+ * Custom render state needed for the various render methods must be extracted via {@link ExtractLevelRenderStateEvent}
+ * and stored in the provided {@link LevelRenderState}.
+ *
+ * @see RegisterCustomEnvironmentEffectRendererEvent#registerSkyboxRenderer
+ * @see net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_SKYBOX
+ */
+public interface CustomSkyboxRenderer {
+ /**
+ * Renders the sky of this dimension.
+ *
+ * @return true to prevent vanilla sky rendering
+ */
+ default boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRenderState, Matrix4f modelViewMatrix, Runnable setupFog) {
+ return false;
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/IDimensionSpecialEffectsExtension.java b/src/client/java/net/neoforged/neoforge/client/CustomWeatherEffectRenderer.java
similarity index 55%
rename from src/client/java/net/neoforged/neoforge/client/extensions/IDimensionSpecialEffectsExtension.java
rename to src/client/java/net/neoforged/neoforge/client/CustomWeatherEffectRenderer.java
index 6efa5e17980..ec1d685b83a 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/IDimensionSpecialEffectsExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/CustomWeatherEffectRenderer.java
@@ -1,46 +1,30 @@
/*
- * Copyright (c) Forge Development LLC and contributors
+ * Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
-package net.neoforged.neoforge.client.extensions;
+package net.neoforged.neoforge.client;
import net.minecraft.client.Camera;
-import net.minecraft.client.CloudStatus;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.state.LevelRenderState;
-import net.minecraft.client.renderer.state.SkyRenderState;
import net.minecraft.client.renderer.state.WeatherRenderState;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.client.event.ExtractLevelRenderStateEvent;
-import org.joml.Matrix4f;
+import net.neoforged.neoforge.client.event.RegisterCustomEnvironmentEffectRendererEvent;
/**
- * Extension interface for {@link DimensionSpecialEffects}.
+ * A custom renderer for snow and rain that can be registered using {@link RegisterCustomEnvironmentEffectRendererEvent#registerWeatherEffectRenderer}
+ * and used with {@link net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_WEATHER_EFFECTS}.
*
* Custom render state needed for the various render methods must be extracted via {@link ExtractLevelRenderStateEvent}
* and stored in the provided {@link LevelRenderState}.
+ *
+ * @see RegisterCustomEnvironmentEffectRendererEvent#registerWeatherEffectRenderer
+ * @see net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_WEATHER_EFFECTS
*/
-public interface IDimensionSpecialEffectsExtension {
- /**
- * Renders the clouds of this dimension.
- *
- * @return true to prevent vanilla cloud rendering
- */
- default boolean renderClouds(LevelRenderState levelRenderState, Vec3 camPos, CloudStatus cloudStatus, int cloudColor, float cloudHeight, Matrix4f modelViewMatrix) {
- return false;
- }
-
- /**
- * Renders the sky of this dimension.
- *
- * @return true to prevent vanilla sky rendering
- */
- default boolean renderSky(LevelRenderState levelRenderState, SkyRenderState skyRenderState, Matrix4f modelViewMatrix, Runnable setupFog) {
- return false;
- }
-
+public interface CustomWeatherEffectRenderer {
/**
* Renders the snow and rain effects of this dimension.
*
diff --git a/src/client/java/net/neoforged/neoforge/client/DimensionSpecialEffectsManager.java b/src/client/java/net/neoforged/neoforge/client/DimensionSpecialEffectsManager.java
deleted file mode 100644
index 9ed869e7307..00000000000
--- a/src/client/java/net/neoforged/neoforge/client/DimensionSpecialEffectsManager.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) Forge Development LLC and contributors
- * SPDX-License-Identifier: LGPL-2.1-only
- */
-
-package net.neoforged.neoforge.client;
-
-import com.google.common.collect.ImmutableMap;
-import java.util.HashMap;
-import net.minecraft.resources.Identifier;
-import net.neoforged.fml.ModLoader;
-import net.neoforged.neoforge.client.event.RegisterDimensionSpecialEffectsEvent;
-import net.neoforged.neoforge.client.extensions.IDimensionSpecialEffectsExtension;
-import org.jetbrains.annotations.ApiStatus;
-
-/**
- * Manager for {@link DimensionSpecialEffects} instances.
- *
- * Provides a lookup by dimension type.
- */
-public final class DimensionSpecialEffectsManager {
- private static ImmutableMap EFFECTS;
- private static IDimensionSpecialEffectsExtension DEFAULT_EFFECTS = new IDimensionSpecialEffectsExtension() {};
-
- /**
- * Finds the {@link DimensionSpecialEffects} for a given dimension type, or the default if none is registered.
- */
- public static IDimensionSpecialEffectsExtension getForType(Identifier type) {
- return EFFECTS.getOrDefault(type, DEFAULT_EFFECTS);
- }
-
- @ApiStatus.Internal
- public static void init() {
- var effects = new HashMap();
- var event = new RegisterDimensionSpecialEffectsEvent(effects);
- ModLoader.postEventWrapContainerInModOrder(event);
- EFFECTS = ImmutableMap.copyOf(effects);
- }
-
- public static IDimensionSpecialEffectsExtension getDefaultEffects() {
- return DEFAULT_EFFECTS;
- }
-
- private DimensionSpecialEffectsManager() {}
-}
diff --git a/src/client/java/net/neoforged/neoforge/client/DimensionTransitionScreenManager.java b/src/client/java/net/neoforged/neoforge/client/DimensionTransitionScreenManager.java
index 1c723f81486..23c65e31d01 100644
--- a/src/client/java/net/neoforged/neoforge/client/DimensionTransitionScreenManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/DimensionTransitionScreenManager.java
@@ -15,7 +15,7 @@
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.RegisterDimensionTransitionScreenEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class DimensionTransitionScreenManager {
private static final Map, ResourceKey>, ReceivingLevelScreenFactory> conditionalDimensionEffects = new HashMap<>();
diff --git a/src/client/java/net/neoforged/neoforge/client/EntitySpectatorShaderManager.java b/src/client/java/net/neoforged/neoforge/client/EntitySpectatorShaderManager.java
index 67c612e8465..bd9fe6262de 100644
--- a/src/client/java/net/neoforged/neoforge/client/EntitySpectatorShaderManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/EntitySpectatorShaderManager.java
@@ -13,7 +13,7 @@
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.RegisterEntitySpectatorShadersEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Manager for entity spectator mode shaders.
diff --git a/src/client/java/net/neoforged/neoforge/client/FireworkShapeFactoryRegistry.java b/src/client/java/net/neoforged/neoforge/client/FireworkShapeFactoryRegistry.java
index 76751f27455..2bc518e00a2 100644
--- a/src/client/java/net/neoforged/neoforge/client/FireworkShapeFactoryRegistry.java
+++ b/src/client/java/net/neoforged/neoforge/client/FireworkShapeFactoryRegistry.java
@@ -9,7 +9,7 @@
import java.util.Map;
import net.minecraft.client.particle.FireworkParticles;
import net.minecraft.world.item.component.FireworkExplosion;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Keeps track of custom firework shape types, because Particle is client side only this can't be on the Shape itself.
diff --git a/src/client/java/net/neoforged/neoforge/client/NamedRenderTypeManager.java b/src/client/java/net/neoforged/neoforge/client/NamedRenderTypeManager.java
index 22e8e0dc208..9323773efb5 100644
--- a/src/client/java/net/neoforged/neoforge/client/NamedRenderTypeManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/NamedRenderTypeManager.java
@@ -43,13 +43,10 @@ public static void init() {
* Pre-registers vanilla render types.
*/
private static void preRegisterVanillaRenderTypes(Map blockRenderTypes) {
- blockRenderTypes.put(Identifier.withDefaultNamespace("solid"), new RenderTypeGroup(ChunkSectionLayer.SOLID, NeoForgeRenderTypes.ITEM_LAYERED_SOLID.get()));
- blockRenderTypes.put(Identifier.withDefaultNamespace("cutout"), new RenderTypeGroup(ChunkSectionLayer.CUTOUT, NeoForgeRenderTypes.ITEM_LAYERED_CUTOUT.get()));
- // Generally entity/item rendering shouldn't use mipmaps, so cutout_mipped has them off by default. To enforce them, use cutout_mipped_all.
- // TODO 1.21.11: Investigate how to deal with block atlas/item atlas split -> blockRenderTypes.put(Identifier.withDefaultNamespace("cutout_mipped"), new RenderTypeGroup(ChunkSectionLayer.CUTOUT_MIPPED, NeoForgeRenderTypes.ITEM_LAYERED_CUTOUT.get()));
- // TODO 1.21.11: Investigate how to deal with block atlas/item atlas split -> blockRenderTypes.put(Identifier.withDefaultNamespace("cutout_mipped_all"), new RenderTypeGroup(ChunkSectionLayer.CUTOUT_MIPPED, NeoForgeRenderTypes.ITEM_LAYERED_CUTOUT_MIPPED.get()));
- blockRenderTypes.put(Identifier.withDefaultNamespace("translucent"), new RenderTypeGroup(ChunkSectionLayer.TRANSLUCENT, NeoForgeRenderTypes.ITEM_LAYERED_TRANSLUCENT.get()));
- blockRenderTypes.put(Identifier.withDefaultNamespace("tripwire"), new RenderTypeGroup(ChunkSectionLayer.TRIPWIRE, NeoForgeRenderTypes.ITEM_LAYERED_TRANSLUCENT.get()));
+ blockRenderTypes.put(Identifier.withDefaultNamespace("solid"), new RenderTypeGroup(ChunkSectionLayer.SOLID, NeoForgeRenderTypes::getItemLayeredSolid));
+ blockRenderTypes.put(Identifier.withDefaultNamespace("cutout"), new RenderTypeGroup(ChunkSectionLayer.CUTOUT, NeoForgeRenderTypes::getItemLayeredCutout));
+ blockRenderTypes.put(Identifier.withDefaultNamespace("translucent"), new RenderTypeGroup(ChunkSectionLayer.TRANSLUCENT, NeoForgeRenderTypes::getItemLayeredTranslucent));
+ blockRenderTypes.put(Identifier.withDefaultNamespace("tripwire"), new RenderTypeGroup(ChunkSectionLayer.TRIPWIRE, NeoForgeRenderTypes::getItemLayeredTranslucent));
}
private NamedRenderTypeManager() {}
diff --git a/src/client/java/net/neoforged/neoforge/client/NeoForgeRenderTypes.java b/src/client/java/net/neoforged/neoforge/client/NeoForgeRenderTypes.java
index 7b725f08dc8..c8940d3031b 100644
--- a/src/client/java/net/neoforged/neoforge/client/NeoForgeRenderTypes.java
+++ b/src/client/java/net/neoforged/neoforge/client/NeoForgeRenderTypes.java
@@ -14,6 +14,7 @@
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.renderer.rendertype.RenderSetup;
import net.minecraft.client.renderer.rendertype.RenderType;
+import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.resources.Identifier;
import net.minecraft.util.Util;
@@ -21,13 +22,18 @@
@SuppressWarnings("deprecation")
public enum NeoForgeRenderTypes {
- ITEM_LAYERED_SOLID(() -> getItemLayeredSolid(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_LAYERED_CUTOUT(() -> getItemLayeredCutout(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_LAYERED_CUTOUT_MIPPED(() -> getItemLayeredCutoutMipped(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_LAYERED_TRANSLUCENT(() -> getItemLayeredTranslucent(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_UNSORTED_TRANSLUCENT(() -> getUnsortedTranslucent(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_UNLIT_TRANSLUCENT(() -> getUnlitTranslucent(TextureAtlas.LOCATION_BLOCKS)),
- ITEM_UNSORTED_UNLIT_TRANSLUCENT(() -> getUnlitTranslucent(TextureAtlas.LOCATION_BLOCKS, false));
+ BLOCK_ITEM_LAYERED_SOLID(() -> getItemLayeredSolid(TextureAtlas.LOCATION_BLOCKS)),
+ BLOCK_ITEM_LAYERED_CUTOUT(() -> getItemLayeredCutout(TextureAtlas.LOCATION_BLOCKS)),
+ BLOCK_ITEM_LAYERED_TRANSLUCENT(() -> getItemLayeredTranslucent(TextureAtlas.LOCATION_BLOCKS)),
+ BLOCK_ITEM_UNSORTED_TRANSLUCENT(() -> getUnsortedTranslucent(TextureAtlas.LOCATION_BLOCKS)),
+ BLOCK_ITEM_UNLIT_TRANSLUCENT(() -> getUnlitTranslucent(TextureAtlas.LOCATION_BLOCKS)),
+ BLOCK_ITEM_UNSORTED_UNLIT_TRANSLUCENT(() -> getUnlitUnsortedTranslucent(TextureAtlas.LOCATION_BLOCKS)),
+ ITEM_LAYERED_SOLID(() -> getItemLayeredSolid(TextureAtlas.LOCATION_ITEMS)),
+ ITEM_LAYERED_CUTOUT(() -> getItemLayeredCutout(TextureAtlas.LOCATION_ITEMS)),
+ ITEM_LAYERED_TRANSLUCENT(() -> getItemLayeredTranslucent(TextureAtlas.LOCATION_ITEMS)),
+ ITEM_UNSORTED_TRANSLUCENT(() -> getUnsortedTranslucent(TextureAtlas.LOCATION_ITEMS)),
+ ITEM_UNLIT_TRANSLUCENT(() -> getUnlitTranslucent(TextureAtlas.LOCATION_ITEMS)),
+ ITEM_UNSORTED_UNLIT_TRANSLUCENT(() -> getUnlitUnsortedTranslucent(TextureAtlas.LOCATION_ITEMS));
// TODO 1.21.11: Some render types previously enabled linear filtering, this intends to be equivalent, but was not checked. Also check the mipmap flag.
private static final Supplier LINEAR_FILTERING_SAMPLER = () -> RenderSystem.getSamplerCache()
@@ -47,13 +53,6 @@ public static RenderType getItemLayeredCutout(Identifier textureLocation) {
return Internal.LAYERED_ITEM_CUTOUT.apply(textureLocation);
}
- /**
- * @return A RenderType fit for multi-layer cutout-mipped item rendering.
- */
- public static RenderType getItemLayeredCutoutMipped(Identifier textureLocation) {
- return Internal.LAYERED_ITEM_CUTOUT_MIPPED.apply(textureLocation);
- }
-
/**
* @return A RenderType fit for multi-layer translucent item rendering.
*/
@@ -79,56 +78,55 @@ public static RenderType getUnlitTranslucent(Identifier textureLocation) {
/**
* @return A RenderType fit for translucent item/entity rendering, but with diffuse lighting disabled
* so that fullbright quads look correct.
- * @param sortingEnabled If false, depth sorting will not be performed.
*/
- public static RenderType getUnlitTranslucent(Identifier textureLocation, boolean sortingEnabled) {
- return (sortingEnabled ? Internal.UNLIT_TRANSLUCENT_SORTED : Internal.UNLIT_TRANSLUCENT_UNSORTED).apply(textureLocation);
+ public static RenderType getUnlitUnsortedTranslucent(Identifier textureLocation) {
+ return Internal.UNLIT_TRANSLUCENT_UNSORTED.apply(textureLocation);
}
/**
- * @return Same as {@link RenderType#entityCutout(Identifier)}, but with mipmapping enabled.
+ * @return Same as {@link RenderTypes#entityCutout(Identifier)}, but with mipmapping enabled.
*/
public static RenderType getEntityCutoutMipped(Identifier textureLocation) {
return Internal.LAYERED_ITEM_CUTOUT_MIPPED.apply(textureLocation);
}
/**
- * @return Replacement of {@link RenderType#text(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#text(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextFiltered(Identifier locationIn) {
return Internal.TEXT_FILTERED.apply(locationIn);
}
/**
- * @return Replacement of {@link RenderType#textIntensity(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#textIntensity(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextIntensityFiltered(Identifier locationIn) {
return Internal.TEXT_INTENSITY_FILTERED.apply(locationIn);
}
/**
- * @return Replacement of {@link RenderType#textPolygonOffset(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#textPolygonOffset(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextPolygonOffsetFiltered(Identifier locationIn) {
return Internal.TEXT_POLYGON_OFFSET_FILTERED.apply(locationIn);
}
/**
- * @return Replacement of {@link RenderType#textIntensityPolygonOffset(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#textIntensityPolygonOffset(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextIntensityPolygonOffsetFiltered(Identifier locationIn) {
return Internal.TEXT_INTENSITY_POLYGON_OFFSET_FILTERED.apply(locationIn);
}
/**
- * @return Replacement of {@link RenderType#textSeeThrough(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#textSeeThrough(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextSeeThroughFiltered(Identifier locationIn) {
return Internal.TEXT_SEETHROUGH_FILTERED.apply(locationIn);
}
/**
- * @return Replacement of {@link RenderType#textIntensitySeeThrough(Identifier)}, but with linear texture filtering.
+ * @return Replacement of {@link RenderTypes#textIntensitySeeThrough(Identifier)}, but with linear texture filtering.
*/
public static RenderType getTextIntensitySeeThroughFiltered(Identifier locationIn) {
return Internal.TEXT_INTENSITY_SEETHROUGH_FILTERED.apply(locationIn);
diff --git a/src/client/java/net/neoforged/neoforge/client/PresetEditorManager.java b/src/client/java/net/neoforged/neoforge/client/PresetEditorManager.java
index e9fd4a0f7f9..a9579e104d0 100644
--- a/src/client/java/net/neoforged/neoforge/client/PresetEditorManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/PresetEditorManager.java
@@ -13,7 +13,7 @@
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.RegisterPresetEditorsEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public final class PresetEditorManager {
private PresetEditorManager() {} // Utility class
diff --git a/src/client/java/net/neoforged/neoforge/client/RenderTypeGroup.java b/src/client/java/net/neoforged/neoforge/client/RenderTypeGroup.java
index e0a4e110a36..072e9bccd0d 100644
--- a/src/client/java/net/neoforged/neoforge/client/RenderTypeGroup.java
+++ b/src/client/java/net/neoforged/neoforge/client/RenderTypeGroup.java
@@ -5,20 +5,32 @@
package net.neoforged.neoforge.client;
+import com.mojang.blaze3d.vertex.DefaultVertexFormat;
+import java.util.function.Function;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.client.renderer.rendertype.RenderType;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.resources.Identifier;
/**
* A set of functionally equivalent shaders. One using {@link com.mojang.blaze3d.vertex.DefaultVertexFormat#BLOCK},
- * and the other one using {@link com.mojang.blaze3d.vertex.DefaultVertexFormat#NEW_ENTITY}.
+ * and the other two using {@link com.mojang.blaze3d.vertex.DefaultVertexFormat#NEW_ENTITY}.
*/
-public record RenderTypeGroup(ChunkSectionLayer block, RenderType entity) {
+public record RenderTypeGroup(ChunkSectionLayer block, RenderType entityBlock, RenderType entityItem) {
public RenderTypeGroup {
- if ((block == null) != (entity == null))
+ if ((block == null) != (entityBlock == null) || (block == null) != (entityItem == null)) {
throw new IllegalArgumentException("The render types in a group must either be all null, or all non-null.");
+ }
+ if (entityBlock != null && (entityBlock.format() != DefaultVertexFormat.NEW_ENTITY || entityItem.format() != DefaultVertexFormat.NEW_ENTITY)) {
+ throw new IllegalArgumentException("The entity render types must use DefaultVertexFormat.NEW_ENTITY.");
+ }
}
- public static RenderTypeGroup EMPTY = new RenderTypeGroup(null, null);
+ public RenderTypeGroup(ChunkSectionLayer block, Function entity) {
+ this(block, entity.apply(TextureAtlas.LOCATION_BLOCKS), entity.apply(TextureAtlas.LOCATION_ITEMS));
+ }
+
+ public static RenderTypeGroup EMPTY = new RenderTypeGroup(null, null, null);
/**
* {@return true if this group has render types or not. It either has all, or none}
diff --git a/src/client/java/net/neoforged/neoforge/client/RenderTypeHelper.java b/src/client/java/net/neoforged/neoforge/client/RenderTypeHelper.java
index 0961dcb1fc4..ddde6ee305c 100644
--- a/src/client/java/net/neoforged/neoforge/client/RenderTypeHelper.java
+++ b/src/client/java/net/neoforged/neoforge/client/RenderTypeHelper.java
@@ -6,17 +6,26 @@
package net.neoforged.neoforge.client;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.Sheets;
+import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.BlockModelPart;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
+import net.minecraft.client.renderer.item.BlockModelWrapper;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.client.renderer.rendertype.RenderTypes;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.resources.Identifier;
+import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
/**
* Provides helper functions replacing those in {@link ItemBlockRenderTypes}.
*/
+@SuppressWarnings("deprecation")
public final class RenderTypeHelper {
/**
* Provides a {@link RenderType} using {@link DefaultVertexFormat#NEW_ENTITY} for the given {@link DefaultVertexFormat#BLOCK} format.
@@ -27,7 +36,7 @@ public final class RenderTypeHelper {
public static RenderType getEntityRenderType(ChunkSectionLayer chunkSectionLayer) {
if (chunkSectionLayer != ChunkSectionLayer.TRANSLUCENT)
return Sheets.cutoutBlockSheet();
- return Sheets.translucentItemSheet();
+ return Sheets.translucentBlockItemSheet();
}
/**
@@ -45,5 +54,34 @@ public static RenderType getMovingBlockRenderType(ChunkSectionLayer chunkSection
};
}
+ /**
+ * Determines whether the provided quads need use textures from the block atlas or the item atlas and returns the
+ * respective {@link RenderType} getter.
+ *
+ * Mimics the behavior of vanilla's {@link BlockModelWrapper#detectRenderType(List)}.
+ */
+ public static Function detectItemModelRenderType(List quads, RenderTypeGroup renderTypes) {
+ Iterator iterator = quads.iterator();
+ if (!iterator.hasNext()) {
+ return $ -> renderTypes.entityItem();
+ }
+
+ Identifier atlasId = iterator.next().sprite().atlasLocation();
+ while (iterator.hasNext()) {
+ Identifier currAtlasId = iterator.next().sprite().atlasLocation();
+ if (!currAtlasId.equals(atlasId)) {
+ throw new IllegalStateException("Multiple atlases used in model, expected " + atlasId + ", but also got " + currAtlasId);
+ }
+ }
+
+ if (atlasId.equals(TextureAtlas.LOCATION_ITEMS)) {
+ return $ -> renderTypes.entityItem();
+ }
+ if (atlasId.equals(TextureAtlas.LOCATION_BLOCKS)) {
+ return $ -> renderTypes.entityBlock();
+ }
+ throw new IllegalArgumentException("Atlas " + atlasId + " can't be used for item models");
+ }
+
private RenderTypeHelper() {}
}
diff --git a/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationCommandEncoder.java b/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationCommandEncoder.java
index bd49a4b6bd5..20e5651ac23 100644
--- a/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationCommandEncoder.java
+++ b/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationCommandEncoder.java
@@ -18,7 +18,7 @@
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.Supplier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Validation wrapper around CommandEncoder
@@ -152,7 +152,7 @@ public void writeToTexture(GpuTexture texture, ByteBuffer imageData, NativeImage
}
@Override
- public void copyTextureToBuffer(GpuTexture texture, GpuBuffer buffer, int bufferOffset, Runnable callback, int mipLevel) {
+ public void copyTextureToBuffer(GpuTexture texture, GpuBuffer buffer, long bufferOffset, Runnable callback, int mipLevel) {
if (!(texture instanceof ValidationGpuTexture validationTexture)) {
throw new IllegalArgumentException();
}
@@ -160,7 +160,7 @@ public void copyTextureToBuffer(GpuTexture texture, GpuBuffer buffer, int buffer
}
@Override
- public void copyTextureToBuffer(GpuTexture texture, GpuBuffer buffer, int bufferOffset, Runnable callback, int mipLevel, int x, int y, int width, int height) {
+ public void copyTextureToBuffer(GpuTexture texture, GpuBuffer buffer, long bufferOffset, Runnable callback, int mipLevel, int x, int y, int width, int height) {
if (!(texture instanceof ValidationGpuTexture validationTexture)) {
throw new IllegalArgumentException();
}
diff --git a/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationGpuDevice.java b/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationGpuDevice.java
index c4fd24e9d65..c1add833dc9 100644
--- a/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationGpuDevice.java
+++ b/src/client/java/net/neoforged/neoforge/client/blaze3d/validation/ValidationGpuDevice.java
@@ -24,7 +24,7 @@
import net.neoforged.neoforge.client.blaze3d.GpuDeviceFeatures;
import net.neoforged.neoforge.client.blaze3d.GpuDeviceProperties;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* The validation GpuDevice is used to ensure that both mods and backends are complying with the B3D API contract correctly.
@@ -103,7 +103,7 @@ public GpuTextureView createTextureView(GpuTexture texture, int baseMipLevel, in
}
@Override
- public GpuBuffer createBuffer(@Nullable Supplier label, int usage, int size) {
+ public GpuBuffer createBuffer(@Nullable Supplier label, int usage, long size) {
validator.validateBufferUsage(usage);
return realDevice.createBuffer(label, usage, size);
}
diff --git a/src/client/java/net/neoforged/neoforge/client/color/item/FluidContentsTint.java b/src/client/java/net/neoforged/neoforge/client/color/item/FluidContentsTint.java
index 7e38a9dc7b2..f6b16270145 100644
--- a/src/client/java/net/neoforged/neoforge/client/color/item/FluidContentsTint.java
+++ b/src/client/java/net/neoforged/neoforge/client/color/item/FluidContentsTint.java
@@ -13,7 +13,7 @@
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.client.model.item.DynamicFluidContainerModel;
import net.neoforged.neoforge.transfer.fluid.FluidUtil;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Returns the tint color of the fluid contained in the item stack.
diff --git a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationHolder.java b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationHolder.java
index ffbdcf9408d..ffff5d35a6a 100644
--- a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationHolder.java
+++ b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationHolder.java
@@ -9,7 +9,7 @@
import java.util.Map;
import net.minecraft.client.animation.AnimationDefinition;
import net.minecraft.resources.Identifier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationLoader.java b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationLoader.java
index f7e2d823409..c8297a8169f 100644
--- a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationLoader.java
+++ b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationLoader.java
@@ -22,7 +22,7 @@
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
import net.minecraft.util.Util;
import net.neoforged.neoforge.resource.ContextAwareReloadListener;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationTypeManager.java b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationTypeManager.java
index ebc7edde89e..5112fc792c4 100644
--- a/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationTypeManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/entity/animation/json/AnimationTypeManager.java
@@ -17,7 +17,7 @@
import net.neoforged.neoforge.client.entity.animation.AnimationTarget;
import net.neoforged.neoforge.client.event.RegisterJsonAnimationTypesEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Manager for custom {@link AnimationTarget}s and {@link AnimationChannel.Interpolation interpolation function}s.
@@ -85,8 +85,7 @@ public static Codec getKeyframeCodec(AnimationTarget target) {
/**
* Gets the {@link AnimationChannel.Interpolation interpolation function} associated with the given {@code name}.
*/
- @Nullable
- public static AnimationChannel.Interpolation getInterpolation(Identifier name) {
+ public static AnimationChannel.@Nullable Interpolation getInterpolation(Identifier name) {
return INTERPOLATIONS.get(name);
}
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ClientChatReceivedEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ClientChatReceivedEvent.java
index f886ff803ec..8ff0fe07feb 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ClientChatReceivedEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ClientChatReceivedEvent.java
@@ -15,7 +15,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when a chat message is received on the client.
@@ -31,12 +31,11 @@
*/
public class ClientChatReceivedEvent extends Event implements ICancellableEvent {
private Component message;
- @Nullable
- private final ChatType.Bound boundChatType;
+ private final ChatType.@Nullable Bound boundChatType;
private final UUID sender;
@ApiStatus.Internal
- public ClientChatReceivedEvent(@Nullable ChatType.Bound boundChatType, Component message, UUID sender) {
+ public ClientChatReceivedEvent(ChatType.@Nullable Bound boundChatType, Component message, UUID sender) {
this.boundChatType = boundChatType;
this.message = message;
this.sender = sender;
@@ -64,8 +63,7 @@ public void setMessage(Component message) {
*
* This may be {@code null} when the message doesn't have a specific source (i.e. for system messages).
*/
- @Nullable
- public ChatType.Bound getBoundChatType() {
+ public ChatType.@Nullable Bound getBoundChatType() {
return this.boundChatType;
}
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ClientPlayerNetworkEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ClientPlayerNetworkEvent.java
index 5ca2992e045..3b4e4dd3d25 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ClientPlayerNetworkEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ClientPlayerNetworkEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired for different client connectivity events.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/EntityRenderersEvent.java b/src/client/java/net/neoforged/neoforge/client/event/EntityRenderersEvent.java
index 9c9117b7456..b6649ddfd14 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/EntityRenderersEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/EntityRenderersEvent.java
@@ -40,7 +40,7 @@
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.neoforge.client.ClientHooks;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired for on different events/actions relating to {@linkplain EntityRenderer entity renderers}.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ExtractLevelRenderStateEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ExtractLevelRenderStateEvent.java
index 00cfceec36e..30047da0c43 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ExtractLevelRenderStateEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ExtractLevelRenderStateEvent.java
@@ -15,13 +15,13 @@
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.LogicalSide;
-import net.neoforged.neoforge.client.extensions.IDimensionSpecialEffectsExtension;
+import net.neoforged.neoforge.client.CustomEnvironmentEffectsRendererManager;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
/**
* Fired when the {@link LevelRenderer} extracts level render state, after all vanilla states have been extracted.
- * Use this event to extract custom render state for use in {@link RenderLevelStageEvent} or {@link IDimensionSpecialEffectsExtension}.
+ * Use this event to extract custom render state for use in {@link RenderLevelStageEvent} or {@linkplain CustomEnvironmentEffectsRendererManager custom environmental effects}.
* Custom data can be stored on and retrieved from the provided {@link LevelRenderState} via {@link LevelRenderState#setRenderData(ContextKey, Object)}
* and {@link LevelRenderState#getRenderData(ContextKey)} respectively.
*
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RegisterCustomEnvironmentEffectRendererEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RegisterCustomEnvironmentEffectRendererEvent.java
new file mode 100644
index 00000000000..f985f371f8b
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/event/RegisterCustomEnvironmentEffectRendererEvent.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) Forge Development LLC and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client.event;
+
+import java.util.Map;
+import net.minecraft.resources.Identifier;
+import net.neoforged.bus.api.Event;
+import net.neoforged.bus.api.ICancellableEvent;
+import net.neoforged.fml.LogicalSide;
+import net.neoforged.fml.event.IModBusEvent;
+import net.neoforged.neoforge.client.CustomCloudsRenderer;
+import net.neoforged.neoforge.client.CustomSkyboxRenderer;
+import net.neoforged.neoforge.client.CustomWeatherEffectRenderer;
+import net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes;
+import org.jetbrains.annotations.ApiStatus;
+
+/**
+ * Allows users to register custom environmental effect renderers, such as {@link CustomCloudsRenderer},
+ * {@link CustomSkyboxRenderer} or {@link CustomWeatherEffectRenderer}.
+ *
+ *
This event is not {@linkplain ICancellableEvent cancellable}.
+ *
+ *
This event is fired on the mod-specific event bus, only on the {@linkplain LogicalSide#CLIENT logical client}.
+ */
+public class RegisterCustomEnvironmentEffectRendererEvent extends Event implements IModBusEvent {
+ private final Map cloudRenderers;
+ private final Map skyboxRenderers;
+ private final Map weatherEffectsRenderers;
+
+ @ApiStatus.Internal
+ public RegisterCustomEnvironmentEffectRendererEvent(Map cloudRenderers,
+ Map skyboxRenderers,
+ Map weatherEffectsRenderers) {
+ this.cloudRenderers = cloudRenderers;
+ this.skyboxRenderers = skyboxRenderers;
+ this.weatherEffectsRenderers = weatherEffectsRenderers;
+ }
+
+ /**
+ * Registers the renderer for a given custom clouds type.
+ *
+ * @see net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes#CUSTOM_CLOUDS
+ */
+ public void registerCloudRenderer(Identifier id, CustomCloudsRenderer effects) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_CLOUDS.equals(id)) {
+ throw new IllegalArgumentException("You cannot register a renderer for the default clouds");
+ }
+ this.cloudRenderers.put(id, effects);
+ }
+
+ /**
+ * Registers the renderer for a given custom skybox type.
+ *
+ * @see NeoForgeEnvironmentAttributes#CUSTOM_SKYBOX
+ */
+ public void registerSkyboxRenderer(Identifier id, CustomSkyboxRenderer effects) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_SKYBOX.equals(id)) {
+ throw new IllegalArgumentException("You cannot register a renderer for the default skybox");
+ }
+ this.skyboxRenderers.put(id, effects);
+ }
+
+ /**
+ * Registers the renderer for a given custom weather effects type.
+ *
+ * @see NeoForgeEnvironmentAttributes#CUSTOM_WEATHER_EFFECTS
+ */
+ public void registerWeatherEffectRenderer(Identifier id, CustomWeatherEffectRenderer effects) {
+ if (NeoForgeEnvironmentAttributes.DEFAULT_CUSTOM_WEATHER_EFFECTS.equals(id)) {
+ throw new IllegalArgumentException("You cannot register a renderer for the default weather effects");
+ }
+ this.weatherEffectsRenderers.put(id, effects);
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RegisterDebugEntriesEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RegisterDebugEntriesEvent.java
index 361fcf56d53..9164d0987cc 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RegisterDebugEntriesEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RegisterDebugEntriesEvent.java
@@ -21,7 +21,7 @@
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.fml.loading.FMLEnvironment;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Event fired when debug entries are registered.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RegisterDimensionSpecialEffectsEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RegisterDimensionSpecialEffectsEvent.java
deleted file mode 100644
index b953c9244a0..00000000000
--- a/src/client/java/net/neoforged/neoforge/client/event/RegisterDimensionSpecialEffectsEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) Forge Development LLC and contributors
- * SPDX-License-Identifier: LGPL-2.1-only
- */
-
-package net.neoforged.neoforge.client.event;
-
-import java.util.Map;
-import net.minecraft.resources.Identifier;
-import net.neoforged.bus.api.Event;
-import net.neoforged.bus.api.ICancellableEvent;
-import net.neoforged.fml.LogicalSide;
-import net.neoforged.fml.event.IModBusEvent;
-import net.neoforged.neoforge.client.extensions.IDimensionSpecialEffectsExtension;
-import org.jetbrains.annotations.ApiStatus;
-
-/**
- * Allows users to register custom {@link DimensionSpecialEffects} for their dimensions.
- *
- * This event is not {@linkplain ICancellableEvent cancellable}, and does not {@linkplain HasResult have a result}.
- *
- *
This event is fired on the mod-specific event bus, only on the {@linkplain LogicalSide#CLIENT logical client}.
- */
-public class RegisterDimensionSpecialEffectsEvent extends Event implements IModBusEvent {
- private final Map effects;
-
- @ApiStatus.Internal
- public RegisterDimensionSpecialEffectsEvent(Map effects) {
- this.effects = effects;
- }
-
- /**
- * Registers the effects for a given dimension type.
- */
- public void register(Identifier dimensionType, IDimensionSpecialEffectsExtension effects) {
- this.effects.put(dimensionType, effects);
- }
-}
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RegisterGuiLayersEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RegisterGuiLayersEvent.java
index b3c72eb6c28..948659f9d4b 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RegisterGuiLayersEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RegisterGuiLayersEvent.java
@@ -19,7 +19,7 @@
import net.neoforged.neoforge.client.gui.GuiLayerManager;
import net.neoforged.neoforge.client.gui.VanillaGuiLayers;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Allows users to register custom {@link GuiLayer layers} for GUI rendering.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RegisterNamedRenderTypesEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RegisterNamedRenderTypesEvent.java
index 5e79b44c44d..871496a1794 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RegisterNamedRenderTypesEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RegisterNamedRenderTypesEvent.java
@@ -8,6 +8,7 @@
import com.google.common.base.Preconditions;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import java.util.Map;
+import java.util.function.Function;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.resources.Identifier;
@@ -38,11 +39,10 @@ public RegisterNamedRenderTypesEvent(Map renderType
*
* @param key The ID of the group
* @param chunkLayer The {@link ChunkSectionLayer} to render blocks with as part of the terrain
- * @param entityRenderType A {@link RenderType} using {@link DefaultVertexFormat#NEW_ENTITY}
+ * @param entityRenderType A factory for a {@link RenderType} using {@link DefaultVertexFormat#NEW_ENTITY} with the atlas passed to the function
*/
- public void register(Identifier key, ChunkSectionLayer chunkLayer, RenderType entityRenderType) {
+ public void register(Identifier key, ChunkSectionLayer chunkLayer, Function entityRenderType) {
Preconditions.checkArgument(!renderTypes.containsKey(key), "Render type already registered: " + key);
- Preconditions.checkArgument(entityRenderType.format() == DefaultVertexFormat.NEW_ENTITY, "The entity render type must use the NEW_ENTITY vertex format.");
renderTypes.put(key, new RenderTypeGroup(chunkLayer, entityRenderType));
}
}
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RenderLevelStageEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RenderLevelStageEvent.java
index cbcc1a44f92..c937f548f32 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RenderLevelStageEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RenderLevelStageEvent.java
@@ -15,8 +15,8 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.client.IRenderableSection;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
+import org.jspecify.annotations.Nullable;
/**
* Fires at various times during {@linkplain LevelRenderer#renderLevel} and {@linkplain GameRenderer#renderLevel}.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RenderNameTagEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RenderNameTagEvent.java
index f46f2b633fa..5961deec098 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RenderNameTagEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RenderNameTagEvent.java
@@ -17,7 +17,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired before an entity renderer renders the nameplate of an entity.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/RenderTooltipEvent.java b/src/client/java/net/neoforged/neoforge/client/event/RenderTooltipEvent.java
index 9df377e96fb..e0de3920b76 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/RenderTooltipEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/RenderTooltipEvent.java
@@ -24,7 +24,7 @@
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired during tooltip rendering.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ScreenEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ScreenEvent.java
index 22e7e684950..dfbc93a61bf 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ScreenEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ScreenEvent.java
@@ -24,7 +24,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ScreenshotEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ScreenshotEvent.java
index bb77a9126cc..6da41abd345 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ScreenshotEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ScreenshotEvent.java
@@ -15,7 +15,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when a screenshot is taken, but before it is written to disk.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/SelectMusicEvent.java b/src/client/java/net/neoforged/neoforge/client/event/SelectMusicEvent.java
index 67fa93922b3..633f3649e78 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/SelectMusicEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/SelectMusicEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when the {@link net.minecraft.client.sounds.MusicManager} checks what situational music should be used. This fires before the music begins playing.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/ViewportEvent.java b/src/client/java/net/neoforged/neoforge/client/event/ViewportEvent.java
index 337054c1b57..232c1885c21 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/ViewportEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/ViewportEvent.java
@@ -16,7 +16,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired for hooking into the entity view rendering in {@link GameRenderer}.
diff --git a/src/client/java/net/neoforged/neoforge/client/event/sound/PlaySoundEvent.java b/src/client/java/net/neoforged/neoforge/client/event/sound/PlaySoundEvent.java
index 1d3c52d0b19..e2bbf8063d5 100644
--- a/src/client/java/net/neoforged/neoforge/client/event/sound/PlaySoundEvent.java
+++ b/src/client/java/net/neoforged/neoforge/client/event/sound/PlaySoundEvent.java
@@ -10,7 +10,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when a sound is about to be played by the sound engine. This fires before the sound is played and before any
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/BlockStateModelExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/BlockStateModelExtension.java
index 31cf4effce4..e40a4b9308f 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/BlockStateModelExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/BlockStateModelExtension.java
@@ -17,7 +17,7 @@
import net.neoforged.neoforge.common.extensions.IBlockGetterExtension;
import net.neoforged.neoforge.common.extensions.IBlockStateExtension;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface BlockStateModelExtension {
private BlockStateModel self() {
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/IRenderStateExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/IRenderStateExtension.java
index 1170a443ac1..8f1bc937e17 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/IRenderStateExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/IRenderStateExtension.java
@@ -7,7 +7,7 @@
import net.minecraft.util.context.ContextKey;
import net.neoforged.neoforge.client.renderstate.BaseRenderState;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extension class for render state objects. Implemented by {@link BaseRenderState} for
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/IVertexConsumerExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/IVertexConsumerExtension.java
index 26bd37d90de..b542aefeed3 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/IVertexConsumerExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/IVertexConsumerExtension.java
@@ -5,12 +5,9 @@
package net.neoforged.neoforge.client.extensions;
-import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormatElement;
-import java.nio.ByteBuffer;
-import net.minecraft.client.renderer.block.model.BakedQuad;
-import net.neoforged.neoforge.client.model.IQuadTransformer;
+import net.neoforged.neoforge.client.model.quad.BakedNormals;
import org.joml.Matrix3f;
import org.joml.Vector3f;
@@ -31,44 +28,10 @@ default VertexConsumer misc(VertexFormatElement element, int... rawData) {
return self();
}
- /**
- * Variant with no per-vertex shading.
- */
- default void putBulkData(PoseStack.Pose pose, BakedQuad bakedQuad, float red, float green, float blue, float alpha, int packedLight, int packedOverlay, boolean readExistingColor) {
- self().putBulkData(
- pose,
- bakedQuad,
- new float[] { 1.0F, 1.0F, 1.0F, 1.0F },
- red,
- green,
- blue,
- alpha,
- new int[] { packedLight, packedLight, packedLight, packedLight },
- packedOverlay
- // TODO 1.21.11: quads no longer store baked color
- /*, readExistingColor*/
- );
- }
-
- // TODO 1.21.11: This doesn't work anymore since BakedQuad no longer has full vertexdata.
- default int applyBakedLighting(int packedLight, ByteBuffer data) {
- int bl = packedLight & 0xFFFF;
- int sl = (packedLight >> 16) & 0xFFFF;
- int offset = IQuadTransformer.UV2 * 4; // int offset for vertex 0 * 4 bytes per int
- int blBaked = Short.toUnsignedInt(data.getShort(offset));
- int slBaked = Short.toUnsignedInt(data.getShort(offset + 2));
- bl = Math.max(bl, blBaked);
- sl = Math.max(sl, slBaked);
- return bl | (sl << 16);
- }
-
- // TODO 1.21.11: This doesn't work anymore since BakedQuad no longer has full vertexdata.
- default void applyBakedNormals(Vector3f generated, ByteBuffer data, Matrix3f normalTransform) {
- byte nx = data.get(28);
- byte ny = data.get(29);
- byte nz = data.get(30);
- if (nx != 0 || ny != 0 || nz != 0) {
- generated.set(nx / 127f, ny / 127f, nz / 127f);
+ default void applyBakedNormals(Vector3f generated, BakedNormals data, int vertex, Matrix3f normalTransform) {
+ int packed = data.normal(vertex);
+ if (!BakedNormals.isUnspecified(packed)) {
+ BakedNormals.unpack(packed, generated);
generated.mul(normalTransform);
}
}
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerExtension.java
index a49fec5c9ad..1f4b58210d4 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerExtension.java
@@ -11,7 +11,7 @@
import net.minecraft.client.resources.model.ResolvableModel;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.client.resources.model.UnbakedModel;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface ModelBakerExtension {
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerPartCacheExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerPartCacheExtension.java
new file mode 100644
index 00000000000..c09c97cfe0b
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/ModelBakerPartCacheExtension.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client.extensions;
+
+import net.neoforged.neoforge.client.model.quad.BakedColors;
+import net.neoforged.neoforge.client.model.quad.BakedNormals;
+
+public interface ModelBakerPartCacheExtension {
+ default BakedNormals normals(BakedNormals normals) {
+ return normals;
+ }
+
+ default BakedColors colors(BakedColors colors) {
+ return colors;
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/ResolvedModelExtension.java b/src/client/java/net/neoforged/neoforge/client/extensions/ResolvedModelExtension.java
index dba75168c46..62f1d125988 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/ResolvedModelExtension.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/ResolvedModelExtension.java
@@ -8,7 +8,7 @@
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.util.context.ContextKeySet;
import net.minecraft.util.context.ContextMap;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extension for {@link ResolvedModel}.
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientBlockExtensions.java b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientBlockExtensions.java
index fb8aff7145b..0dcc6679786 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientBlockExtensions.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientBlockExtensions.java
@@ -24,8 +24,8 @@
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.HitResult;
import net.neoforged.fml.LogicalSide;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3d;
+import org.jspecify.annotations.Nullable;
/**
* {@linkplain LogicalSide#CLIENT Client-only} extensions to {@link Block}.
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java
index f114fc957c8..20c525f05dc 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java
@@ -25,8 +25,8 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidType;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f;
+import org.jspecify.annotations.Nullable;
/**
* {@linkplain LogicalSide#CLIENT Client-only} extensions to {@link FluidType}.
diff --git a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientItemExtensions.java b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientItemExtensions.java
index 89933781caa..8e904e0fac2 100644
--- a/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientItemExtensions.java
+++ b/src/client/java/net/neoforged/neoforge/client/extensions/common/IClientItemExtensions.java
@@ -30,7 +30,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.client.ClientHooks;
import net.neoforged.neoforge.client.IArmPoseTransformer;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* {@linkplain LogicalSide#CLIENT Client-only} extensions to {@link Item}.
@@ -70,8 +70,7 @@ default Font getFont(ItemStack stack, FontContext context) {
* @param itemStack The stack being held
* @return A custom ArmPose that can be used to define movement of the arm
*/
- @Nullable
- default HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack itemStack) {
+ default HumanoidModel.@Nullable ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack itemStack) {
return null;
}
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/ClientTooltipComponentManager.java b/src/client/java/net/neoforged/neoforge/client/gui/ClientTooltipComponentManager.java
index 4ca0ce7fe43..1dc6b8bd109 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/ClientTooltipComponentManager.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/ClientTooltipComponentManager.java
@@ -13,7 +13,7 @@
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Manager for {@link ClientTooltipComponent} factories.
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/ConfigurationScreen.java b/src/client/java/net/neoforged/neoforge/client/gui/ConfigurationScreen.java
index f1f131ee71b..749bec4d845 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/ConfigurationScreen.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/ConfigurationScreen.java
@@ -77,7 +77,7 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/LoadingErrorScreen.java b/src/client/java/net/neoforged/neoforge/client/gui/LoadingErrorScreen.java
index cab854073a2..b3782ba2e8f 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/LoadingErrorScreen.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/LoadingErrorScreen.java
@@ -26,7 +26,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
public class LoadingErrorScreen extends ErrorScreen {
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/ModListScreen.java b/src/client/java/net/neoforged/neoforge/client/gui/ModListScreen.java
index 7f716396ff0..0fa69e3d9ad 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/ModListScreen.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/ModListScreen.java
@@ -63,7 +63,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ComparableVersion;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class ModListScreen extends Screen {
private static String stripControlCodes(String value) {
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/ModMismatchDisconnectedScreen.java b/src/client/java/net/neoforged/neoforge/client/gui/ModMismatchDisconnectedScreen.java
index b1cb1a3c4ed..d78f2a303ad 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/ModMismatchDisconnectedScreen.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/ModMismatchDisconnectedScreen.java
@@ -41,7 +41,7 @@
import net.neoforged.neoforge.client.gui.widget.ScrollPanel;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.commons.lang3.tuple.Pair;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class ModMismatchDisconnectedScreen extends Screen {
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/PictureInPictureRendererPool.java b/src/client/java/net/neoforged/neoforge/client/gui/PictureInPictureRendererPool.java
index 29dd2503a62..b730ed63b50 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/PictureInPictureRendererPool.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/PictureInPictureRendererPool.java
@@ -14,7 +14,7 @@
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
import net.minecraft.client.renderer.MultiBufferSource;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Pools {@link PictureInPictureRenderer} for a single type of {@link PictureInPictureRenderState} and tries
diff --git a/src/client/java/net/neoforged/neoforge/client/gui/widget/ModsButton.java b/src/client/java/net/neoforged/neoforge/client/gui/widget/ModsButton.java
index e8772b572d2..15d64c31705 100644
--- a/src/client/java/net/neoforged/neoforge/client/gui/widget/ModsButton.java
+++ b/src/client/java/net/neoforged/neoforge/client/gui/widget/ModsButton.java
@@ -14,7 +14,7 @@
import net.neoforged.neoforge.client.loading.ClientModLoader;
import net.neoforged.neoforge.common.NeoForgeMod;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Custom button subclass to draw an indicator overlay on the button when updates are available.
@@ -23,8 +23,7 @@
public class ModsButton extends Button.Plain {
private static final Identifier VERSION_CHECK_ICONS = Identifier.fromNamespaceAndPath(NeoForgeMod.MOD_ID, "textures/gui/version_check_icons.png");
- @Nullable
- private VersionChecker.Status showNotification;
+ private VersionChecker.@Nullable Status showNotification;
private boolean hasCheckedForUpdates = false;
public ModsButton(Builder builder) {
diff --git a/src/client/java/net/neoforged/neoforge/client/internal/NeoForgeClientProxy.java b/src/client/java/net/neoforged/neoforge/client/internal/NeoForgeClientProxy.java
index 783f81fe657..c7378465318 100644
--- a/src/client/java/net/neoforged/neoforge/client/internal/NeoForgeClientProxy.java
+++ b/src/client/java/net/neoforged/neoforge/client/internal/NeoForgeClientProxy.java
@@ -14,7 +14,7 @@
import net.minecraft.world.item.TooltipFlag;
import net.neoforged.neoforge.internal.NeoForgeProxy;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
public class NeoForgeClientProxy extends NeoForgeProxy {
@@ -29,8 +29,7 @@ public TooltipFlag getTooltipFlag() {
}
@Override
- @Nullable
- public HolderLookup.RegistryLookup resolveLookup(ResourceKey extends Registry> key) {
+ public HolderLookup.@Nullable RegistryLookup resolveLookup(ResourceKey extends Registry> key) {
var lookup = super.resolveLookup(key);
if (lookup == null) {
ClientLevel level = Minecraft.getInstance().level;
diff --git a/src/client/java/net/neoforged/neoforge/client/loading/ClientModLoader.java b/src/client/java/net/neoforged/neoforge/client/loading/ClientModLoader.java
index 67485e46189..7478c31b442 100644
--- a/src/client/java/net/neoforged/neoforge/client/loading/ClientModLoader.java
+++ b/src/client/java/net/neoforged/neoforge/client/loading/ClientModLoader.java
@@ -33,7 +33,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
public class ClientModLoader extends CommonModLoader {
diff --git a/src/client/java/net/neoforged/neoforge/client/model/AbstractUnbakedModel.java b/src/client/java/net/neoforged/neoforge/client/model/AbstractUnbakedModel.java
index c0526dba879..c67cef89a20 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/AbstractUnbakedModel.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/AbstractUnbakedModel.java
@@ -14,7 +14,7 @@
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.Identifier;
import net.minecraft.util.context.ContextMap;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Base unbaked model for custom models which support the standard top-level model parameters
diff --git a/src/client/java/net/neoforged/neoforge/client/model/DelegateUnbakedModel.java b/src/client/java/net/neoforged/neoforge/client/model/DelegateUnbakedModel.java
index b9711786022..7842672b142 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/DelegateUnbakedModel.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/DelegateUnbakedModel.java
@@ -11,7 +11,7 @@
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.Identifier;
import net.minecraft.util.context.ContextMap;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public abstract class DelegateUnbakedModel implements UnbakedModel {
protected final UnbakedModel delegate;
diff --git a/src/client/java/net/neoforged/neoforge/client/model/ExtraFaceData.java b/src/client/java/net/neoforged/neoforge/client/model/ExtraFaceData.java
index 096f0853b8c..8d770be9633 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/ExtraFaceData.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/ExtraFaceData.java
@@ -14,19 +14,18 @@
import java.util.function.Function;
import net.minecraft.client.renderer.block.model.BlockElement;
import net.minecraft.client.renderer.block.model.BlockElementFace;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Holds extra data that may be injected into a face.
* Used by {@link ItemLayerModel}, {@link BlockElement} and {@link BlockElementFace}
*
* @param color Color in ARGB format
- * @param blockLight Block Light for this face from 0-15 (inclusive)
- * @param skyLight Sky Light for this face from 0-15 (inclusive)
+ * @param lightEmission Light emission for the face or element from 0-15 (inclusive)
* @param ambientOcclusion If this face has AO
*/
-public record ExtraFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion) {
- public static final ExtraFaceData DEFAULT = new ExtraFaceData(0xFFFFFFFF, 0, 0, true);
+public record ExtraFaceData(int color, int lightEmission, boolean ambientOcclusion) {
+ public static final ExtraFaceData DEFAULT = new ExtraFaceData(0xFFFFFFFF, 0, true);
public static final Codec COLOR = Codec.either(Codec.INT, Codec.STRING).xmap(
either -> either.map(Function.identity(), str -> (int) Long.parseLong(str, 16)),
@@ -36,8 +35,7 @@ public record ExtraFaceData(int color, int blockLight, int skyLight, boolean amb
builder -> builder
.group(
COLOR.optionalFieldOf("color", 0xFFFFFFFF).forGetter(ExtraFaceData::color),
- Codec.intRange(0, 15).optionalFieldOf("block_light", 0).forGetter(ExtraFaceData::blockLight),
- Codec.intRange(0, 15).optionalFieldOf("sky_light", 0).forGetter(ExtraFaceData::skyLight),
+ Codec.intRange(0, 15).optionalFieldOf("light_emission", 0).forGetter(ExtraFaceData::lightEmission),
Codec.BOOL.optionalFieldOf("ambient_occlusion", true).forGetter(ExtraFaceData::ambientOcclusion))
.apply(builder, ExtraFaceData::new));
diff --git a/src/client/java/net/neoforged/neoforge/client/model/IQuadTransformer.java b/src/client/java/net/neoforged/neoforge/client/model/IQuadTransformer.java
deleted file mode 100644
index af99fce64ae..00000000000
--- a/src/client/java/net/neoforged/neoforge/client/model/IQuadTransformer.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) Forge Development LLC and contributors
- * SPDX-License-Identifier: LGPL-2.1-only
- */
-
-package net.neoforged.neoforge.client.model;
-
-import com.mojang.blaze3d.vertex.DefaultVertexFormat;
-import com.mojang.blaze3d.vertex.VertexFormatElement;
-import java.util.List;
-import net.minecraft.client.renderer.block.model.BakedQuad;
-
-/**
- * Transformer for {@link BakedQuad baked quads}.
- *
- * @see QuadTransformers
- */
-public interface IQuadTransformer {
- int STRIDE = DefaultVertexFormat.BLOCK.getVertexSize() / 4;
- int POSITION = findOffset(VertexFormatElement.POSITION);
- int COLOR = findOffset(VertexFormatElement.COLOR);
- int UV0 = findOffset(VertexFormatElement.UV0);
- int UV1 = findOffset(VertexFormatElement.UV1);
- int UV2 = findOffset(VertexFormatElement.UV2);
- int NORMAL = findOffset(VertexFormatElement.NORMAL);
-
- void processInPlace(BakedQuad quad);
-
- default void processInPlace(List quads) {
- for (BakedQuad quad : quads)
- processInPlace(quad);
- }
-
- default BakedQuad process(BakedQuad quad) {
- var copy = copy(quad);
- processInPlace(copy);
- return copy;
- }
-
- default List process(List inputs) {
- return inputs.stream().map(IQuadTransformer::copy).peek(this::processInPlace).toList();
- }
-
- default IQuadTransformer andThen(IQuadTransformer other) {
- return quad -> {
- processInPlace(quad);
- other.processInPlace(quad);
- };
- }
-
- private static BakedQuad copy(BakedQuad quad) {
- // TODO 1.21.11: this is pretty much useless now
- return new BakedQuad(quad.position0(), quad.position1(), quad.position2(), quad.position3(), quad.packedUV0(), quad.packedUV1(), quad.packedUV2(), quad.packedUV3(), quad.tintIndex(), quad.direction(), quad.sprite(), quad.shade(), quad.lightEmission(), quad.hasAmbientOcclusion());
- }
-
- private static int findOffset(VertexFormatElement element) {
- if (DefaultVertexFormat.BLOCK.contains(element)) {
- // Divide by 4 because we want the int offset
- return DefaultVertexFormat.BLOCK.getOffset(element) / 4;
- }
- return -1;
- }
-}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/NeoForgeModelProperties.java b/src/client/java/net/neoforged/neoforge/client/model/NeoForgeModelProperties.java
index 2edf0af5e8a..8f1de4089c0 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/NeoForgeModelProperties.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/NeoForgeModelProperties.java
@@ -19,7 +19,7 @@
import net.minecraft.util.context.ContextMap;
import net.neoforged.neoforge.client.NamedRenderTypeManager;
import net.neoforged.neoforge.client.RenderTypeGroup;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Properties that NeoForge adds for {@link BlockModel}s and {@link UnbakedModel}s.
diff --git a/src/client/java/net/neoforged/neoforge/client/model/QuadTransformers.java b/src/client/java/net/neoforged/neoforge/client/model/QuadTransformers.java
deleted file mode 100644
index 7285f37216f..00000000000
--- a/src/client/java/net/neoforged/neoforge/client/model/QuadTransformers.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) Forge Development LLC and contributors
- * SPDX-License-Identifier: LGPL-2.1-only
- */
-
-package net.neoforged.neoforge.client.model;
-
-import com.google.common.base.Preconditions;
-import com.mojang.math.Transformation;
-import java.util.Arrays;
-import net.minecraft.client.renderer.LightTexture;
-import net.minecraft.client.renderer.block.model.BakedQuad;
-import net.minecraft.util.Util;
-
-/**
- * A collection of {@link IQuadTransformer} implementations.
- *
- * @see IQuadTransformer
- */
-public final class QuadTransformers {
- private static final IQuadTransformer EMPTY = quad -> {};
- private static final IQuadTransformer[] EMISSIVE_TRANSFORMERS = Util.make(new IQuadTransformer[16], array -> {
- Arrays.setAll(array, i -> applyingLightmap(LightTexture.pack(i, i)));
- });
-
- /**
- * {@return a {@link BakedQuad} transformer that does nothing}
- */
- public static IQuadTransformer empty() {
- return EMPTY;
- }
-
- /**
- * {@return a new {@link BakedQuad} transformer that applies the specified {@link Transformation}}
- */
- public static IQuadTransformer applying(Transformation transform) {
- if (transform.isIdentity())
- return empty();
- return quad -> {
- // TODO 1.21.11: quad vertex data can no longer be modified in-place
- /*var vertices = quad.vertices();
- for (int i = 0; i < 4; i++) {
- int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.POSITION;
- float x = Float.intBitsToFloat(vertices[offset]);
- float y = Float.intBitsToFloat(vertices[offset + 1]);
- float z = Float.intBitsToFloat(vertices[offset + 2]);
-
- Vector4f pos = new Vector4f(x, y, z, 1);
- transform.transformPosition(pos);
- pos.div(pos.w);
-
- vertices[offset] = Float.floatToRawIntBits(pos.x());
- vertices[offset + 1] = Float.floatToRawIntBits(pos.y());
- vertices[offset + 2] = Float.floatToRawIntBits(pos.z());
- }
-
- for (int i = 0; i < 4; i++) {
- int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
- int normalIn = vertices[offset];
- if ((normalIn & 0x00FFFFFF) != 0) // The ignored byte is padding and may be filled with user data
- {
- float x = ((byte) (normalIn & 0xFF)) / 127.0f;
- float y = ((byte) ((normalIn >> 8) & 0xFF)) / 127.0f;
- float z = ((byte) ((normalIn >> 16) & 0xFF)) / 127.0f;
-
- Vector3f pos = new Vector3f(x, y, z);
- transform.transformNormal(pos);
-
- vertices[offset] = (((byte) (pos.x() * 127.0f)) & 0xFF) |
- ((((byte) (pos.y() * 127.0f)) & 0xFF) << 8) |
- ((((byte) (pos.z() * 127.0f)) & 0xFF) << 16) |
- (normalIn & 0xFF000000); // Restore padding, just in case
- }
- }*/
- };
- }
-
- /**
- * @return A new {@link BakedQuad} transformer that applies the specified packed light value.
- */
- public static IQuadTransformer applyingLightmap(int packedLight) {
- return quad -> {
- // TODO 1.21.11: quad vertex data can no longer be modified in-place
- //var vertices = quad.vertices();
- //for (int i = 0; i < 4; i++)
- // vertices[i * IQuadTransformer.STRIDE + IQuadTransformer.UV2] = packedLight;
- };
- }
-
- /**
- * @return A new {@link BakedQuad} transformer that applies the specified block and sky light values.
- */
- public static IQuadTransformer applyingLightmap(int blockLight, int skyLight) {
- return applyingLightmap(LightTexture.pack(blockLight, skyLight));
- }
-
- /**
- * @return A {@link BakedQuad} transformer that sets the lightmap to the given emissivity (0-15)
- */
- public static IQuadTransformer settingEmissivity(int emissivity) {
- Preconditions.checkArgument(emissivity >= 0 && emissivity < 16, "Emissivity must be between 0 and 15.");
- return EMISSIVE_TRANSFORMERS[emissivity];
- }
-
- /**
- * @return A {@link BakedQuad} transformer that sets the lightmap to its max value
- */
- public static IQuadTransformer settingMaxEmissivity() {
- return EMISSIVE_TRANSFORMERS[15];
- }
-
- /**
- * @param color The color in ARGB format.
- * @return A {@link BakedQuad} transformer that sets the color to the specified value.
- */
- public static IQuadTransformer applyingColor(int color) {
- final int fixedColor = toABGR(color);
- return quad -> {
- // TODO 1.21.11: quad vertex data can no longer be modified in-place
- //var vertices = quad.vertices();
- //for (int i = 0; i < 4; i++)
- // vertices[i * IQuadTransformer.STRIDE + IQuadTransformer.COLOR] = fixedColor;
- };
- }
-
- /**
- * This method supplies a default alpha value of 255 (no transparency)
- *
- * @param red The red value (0-255)
- * @param green The green value (0-255)
- * @param blue The blue value (0-255)
- * @return A {@link BakedQuad} transformer that sets the color to the specified value.
- */
- public static IQuadTransformer applyingColor(int red, int green, int blue) {
- return applyingColor(255, red, green, blue);
- }
-
- /**
- * @param alpha The alpha value (0-255)
- * @param red The red value (0-255)
- * @param green The green value (0-255)
- * @param blue The blue value (0-255)
- * @return A {@link BakedQuad} transformer that sets the color to the specified value.
- */
- public static IQuadTransformer applyingColor(int alpha, int red, int green, int blue) {
- return applyingColor(alpha << 24 | red << 16 | green << 8 | blue);
- }
-
- /**
- * Converts an ARGB color to an ABGR color, as the commonly used color format is not the format colors end up packed into.
- * This function doubles as its own inverse.
- *
- * @param argb ARGB color
- * @return ABGR color
- */
- public static int toABGR(int argb) {
- return (argb & 0xFF00FF00) // alpha and green same spot
- | ((argb >> 16) & 0x000000FF) // red moves to blue
- | ((argb << 16) & 0x00FF0000); // blue moves to red
- }
-
- private QuadTransformers() {}
-}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/StandardModelParameters.java b/src/client/java/net/neoforged/neoforge/client/model/StandardModelParameters.java
index 7a84ff5034d..22cc7653a3d 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/StandardModelParameters.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/StandardModelParameters.java
@@ -15,7 +15,7 @@
import net.minecraft.resources.Identifier;
import net.minecraft.util.GsonHelper;
import net.neoforged.neoforge.client.RenderTypeGroup;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Wrapper around all standard top-level model parameters added by vanilla and NeoForge except elements.
@@ -28,7 +28,7 @@ public record StandardModelParameters(
TextureSlots.Data textures,
@Nullable ItemTransforms itemTransforms,
@Nullable Boolean ambientOcclusion,
- @Nullable UnbakedModel.GuiLight guiLight,
+ UnbakedModel.@Nullable GuiLight guiLight,
@Nullable Transformation rootTransform,
RenderTypeGroup renderTypeGroup,
Map partVisibility) {
diff --git a/src/client/java/net/neoforged/neoforge/client/model/UnbakedElementsHelper.java b/src/client/java/net/neoforged/neoforge/client/model/UnbakedElementsHelper.java
index 9a5843adab5..60d13828e82 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/UnbakedElementsHelper.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/UnbakedElementsHelper.java
@@ -25,8 +25,8 @@
import net.minecraft.client.resources.model.QuadCollection;
import net.minecraft.core.Direction;
import net.minecraft.resources.Identifier;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
+import org.jspecify.annotations.Nullable;
public final class UnbakedElementsHelper {
private UnbakedElementsHelper() {}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/UnbakedModelParser.java b/src/client/java/net/neoforged/neoforge/client/model/UnbakedModelParser.java
index a802920d8d1..b6f5496b25d 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/UnbakedModelParser.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/UnbakedModelParser.java
@@ -22,7 +22,7 @@
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.ModelEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class UnbakedModelParser {
private static ImmutableMap> LOADERS;
diff --git a/src/client/java/net/neoforged/neoforge/client/model/ao/EnhancedAoRenderStorage.java b/src/client/java/net/neoforged/neoforge/client/model/ao/EnhancedAoRenderStorage.java
index 0cb2138a557..de54f52c0f5 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/ao/EnhancedAoRenderStorage.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/ao/EnhancedAoRenderStorage.java
@@ -14,8 +14,8 @@
import net.minecraft.util.Mth;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
-import net.neoforged.neoforge.client.ClientHooks;
import net.neoforged.neoforge.client.config.NeoForgeClientConfig;
+import net.neoforged.neoforge.client.model.quad.BakedNormals;
import org.joml.Vector3fc;
import org.slf4j.Logger;
@@ -48,21 +48,20 @@ public static void applyFlatQuadBrightness(BlockAndTintGetter level, BakedQuad q
for (int vertex = 0; vertex < 4; ++vertex) {
// Handle each vertex separately to apply vertex normals.
- // TODO 1.21.11: quads can no longer store baked normals
- int normal = 0;//quad.vertices()[IQuadTransformer.STRIDE * vertex + IQuadTransformer.NORMAL];
+ int normal = quad.bakedNormals().normal(vertex);
// The ignored byte is padding and may be filled with user data
- if ((normal & 0x00FFFFFF) == 0) {
+ if (BakedNormals.isUnspecified(normal)) {
// No normal! Try to use the quad normal.
if (quadNormal == -1) {
- quadNormal = ClientHooks.computeQuadNormal(quad.position0(), quad.position1(), quad.position2(), quad.position3());
+ quadNormal = BakedNormals.computeQuadNormal(quad.position0(), quad.position1(), quad.position2(), quad.position3());
}
normal = quadNormal;
}
storage.brightness[vertex] = level.getShade(
- normalComponent(normal, 0),
- normalComponent(normal, 1),
- normalComponent(normal, 2),
+ BakedNormals.unpackX(normal),
+ BakedNormals.unpackY(normal),
+ BakedNormals.unpackZ(normal),
quad.shade());
}
} else {
@@ -194,13 +193,12 @@ private void calculateIrregular(BlockAndTintGetter level, BlockState state, Bloc
for (int vertex = 0; vertex < 4; ++vertex) {
// Handle each vertex separately to apply vertex normals.
- // TODO 1.21.11: quads can no longer store baked normals
- int normal = 0;//vertices[IQuadTransformer.STRIDE * vertex + IQuadTransformer.NORMAL];
+ int normal = currentQuad.bakedNormals().normal(vertex);
// The ignored byte is padding and may be filled with user data
- if ((normal & 0x00FFFFFF) == 0) {
+ if (BakedNormals.isUnspecified(normal)) {
// No normal! Try to use the quad normal.
if (quadNormal == -1) {
- quadNormal = ClientHooks.computeQuadNormal(currentQuad.position0(), currentQuad.position1(), currentQuad.position2(), currentQuad.position3());
+ quadNormal = BakedNormals.computeQuadNormal(currentQuad.position0(), currentQuad.position1(), currentQuad.position2(), currentQuad.position3());
}
normal = quadNormal;
}
@@ -211,7 +209,7 @@ private void calculateIrregular(BlockAndTintGetter level, BlockState state, Bloc
int maxLightmap = 0;
for (int axis = 0; axis < 3; ++axis) {
- float normalComponent = normalComponent(normal, axis);
+ float normalComponent = BakedNormals.unpackComponent(normal, axis);
if (normalComponent == 0) {
continue;
}
@@ -256,16 +254,6 @@ private void calculateIrregular(BlockAndTintGetter level, BlockState state, Bloc
}
}
- /**
- * Unpacks a normal component.
- */
- private static float normalComponent(int normal, int axis) {
- int encodedNormalComponent = (normal >> (axis * 8)) & 0xFF;
- // Casting to byte will cast to a signed int.
- // This is really important, otherwise negative values will lead to above 1.0 normal components.
- return ((byte) encodedNormalComponent) / 127.0f;
- }
-
/**
* Interpolates brightness from the 4 corners of a face.
*/
diff --git a/src/client/java/net/neoforged/neoforge/client/model/block/CompositeBlockModel.java b/src/client/java/net/neoforged/neoforge/client/model/block/CompositeBlockModel.java
index 6ff96cb8ce6..19505274e65 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/block/CompositeBlockModel.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/block/CompositeBlockModel.java
@@ -18,7 +18,7 @@
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.client.model.DynamicBlockStateModel;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class CompositeBlockModel implements DynamicBlockStateModel {
private final List models;
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/blockstate/UnbakedMutator.java b/src/client/java/net/neoforged/neoforge/client/model/generators/blockstate/UnbakedMutator.java
index fcb600eb75c..73dae8efbb9 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/blockstate/UnbakedMutator.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/blockstate/UnbakedMutator.java
@@ -10,7 +10,7 @@
import java.util.Map;
import java.util.function.UnaryOperator;
import net.minecraft.client.renderer.block.model.BlockStateModel;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Implements functionality similar to Vanillas {@link net.minecraft.client.renderer.block.model.VariantMutator},
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/loaders/ObjModelBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/loaders/ObjModelBuilder.java
index 8bcc3183cff..19325bac15c 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/loaders/ObjModelBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/loaders/ObjModelBuilder.java
@@ -10,7 +10,7 @@
import net.minecraft.resources.Identifier;
import net.neoforged.neoforge.client.model.generators.template.CustomLoaderBuilder;
import net.neoforged.neoforge.common.NeoForgeMod;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class ObjModelBuilder extends CustomLoaderBuilder {
@Nullable
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ElementBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ElementBuilder.java
index b073687ed42..258c371b336 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ElementBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ElementBuilder.java
@@ -18,8 +18,8 @@
import net.minecraft.client.renderer.block.model.BlockElementFace;
import net.minecraft.core.Direction;
import net.neoforged.neoforge.client.model.ExtraFaceData;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
+import org.jspecify.annotations.Nullable;
public final class ElementBuilder {
private Vector3f from = new Vector3f();
@@ -30,8 +30,6 @@ public final class ElementBuilder {
private boolean shade = true;
private int lightEmission = 0;
private int color = 0xFFFFFFFF;
- private int blockLight = 0;
- private int skyLight = 0;
private boolean hasAmbientOcclusion = true;
/**
@@ -176,24 +174,8 @@ public ElementBuilder cube(TextureSlot texture) {
return allFaces(addTexture(texture).andThen((dir, f) -> f.cullface(dir)));
}
- /**
- * Set the block and sky light of the element (0-15).
- * Traditional "emissivity" values were set both of these to the same value.
- *
- * @param blockLight the block light
- * @param skyLight the sky light
- * @return this builder
- */
- public ElementBuilder emissivity(int blockLight, int skyLight) {
- this.blockLight = blockLight;
- this.skyLight = skyLight;
- return this;
- }
-
/**
* Set the light emission of the element (0-15)
- *
- * If block and sky light values should be different, use {@link #emissivity(int, int)} instead
*
* @param lightEmission the light value
* @return this builder
@@ -244,7 +226,7 @@ BlockElement build() {
Map faces = this.faces.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().build(), (k1, k2) -> {
throw new IllegalArgumentException();
}, LinkedHashMap::new));
- return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, lightEmission, new ExtraFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion));
+ return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, lightEmission, new ExtraFaceData(this.color, 0, this.hasAmbientOcclusion));
}
ElementBuilder copy() {
@@ -256,8 +238,6 @@ ElementBuilder copy() {
builder.shade = this.shade;
builder.lightEmission = this.lightEmission;
builder.color = this.color;
- builder.blockLight = this.blockLight;
- builder.skyLight = this.skyLight;
builder.hasAmbientOcclusion = this.hasAmbientOcclusion;
return builder;
}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplate.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplate.java
index 1c4a8fda908..71859f215a4 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplate.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplate.java
@@ -22,8 +22,8 @@
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemDisplayContext;
import net.neoforged.neoforge.client.model.ExtraFaceData;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3fc;
+import org.jspecify.annotations.Nullable;
public final class ExtendedModelTemplate extends ModelTemplate {
final Map transforms;
@@ -35,8 +35,7 @@ public final class ExtendedModelTemplate extends ModelTemplate {
final Identifier renderType;
@Nullable
final Boolean ambientOcclusion;
- @Nullable
- final UnbakedModel.GuiLight guiLight;
+ final UnbakedModel.@Nullable GuiLight guiLight;
ExtendedModelTemplate(ExtendedModelTemplateBuilder builder) {
super(builder.parent, builder.suffix, builder.requiredSlots.toArray(TextureSlot[]::new));
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplateBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplateBuilder.java
index 7e4c6f89938..d5b80eff25d 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplateBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/ExtendedModelTemplateBuilder.java
@@ -22,7 +22,7 @@
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemDisplayContext;
import net.neoforged.neoforge.client.event.RegisterNamedRenderTypesEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class ExtendedModelTemplateBuilder {
Optional parent = Optional.empty();
@@ -37,8 +37,7 @@ public class ExtendedModelTemplateBuilder {
Identifier renderType = null;
@Nullable
Boolean ambientOcclusion = null; // UnbakedModel.DEFAULT_AMBIENT_OCCLUSION
- @Nullable
- UnbakedModel.GuiLight guiLight = null;
+ UnbakedModel.@Nullable GuiLight guiLight = null;
public static ExtendedModelTemplateBuilder of(ModelTemplate template) {
ExtendedModelTemplateBuilder builder = new ExtendedModelTemplateBuilder();
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/FaceBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/FaceBuilder.java
index 6263d449aaf..06fe299548b 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/FaceBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/FaceBuilder.java
@@ -12,7 +12,7 @@
import net.minecraft.core.Direction;
import net.neoforged.neoforge.client.model.ExtraFaceData;
import org.apache.commons.lang3.mutable.MutableObject;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public final class FaceBuilder {
@Nullable
@@ -20,12 +20,10 @@ public final class FaceBuilder {
private int tintindex = -1;
@Nullable
private TextureSlot texture = null;
- @Nullable
- private BlockElementFace.UVs uvs;
+ private BlockElementFace.@Nullable UVs uvs;
private Quadrant rotation = Quadrant.R0;
private int color = 0xFFFFFFFF;
- private int blockLight = 0;
- private int skyLight = 0;
+ private int lightEmission = 0;
private boolean hasAmbientOcclusion = true;
/**
@@ -79,16 +77,13 @@ public FaceBuilder rotation(Quadrant rot) {
}
/**
- * Set the block and sky light of the face (0-15).
- * Traditional "emissivity" values set both of these to the same value.
+ * Set the light emission of the face (0-15)
*
- * @param blockLight the block light
- * @param skyLight the sky light
+ * @param lightEmission the light value
* @return this builder
*/
- public FaceBuilder emissivity(int blockLight, int skyLight) {
- this.blockLight = blockLight;
- this.skyLight = skyLight;
+ public FaceBuilder lightEmission(int lightEmission) {
+ this.lightEmission = lightEmission;
return this;
}
@@ -118,7 +113,7 @@ BlockElementFace build() {
if (this.texture == null) {
throw new IllegalStateException("A model face must have a texture");
}
- return new BlockElementFace(cullface, tintindex, texture.toString(), uvs, rotation, new ExtraFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion), new MutableObject<>());
+ return new BlockElementFace(cullface, tintindex, texture.toString(), uvs, rotation, new ExtraFaceData(this.color, this.lightEmission, this.hasAmbientOcclusion), new MutableObject<>());
}
FaceBuilder copy() {
@@ -129,8 +124,7 @@ FaceBuilder copy() {
builder.tintindex = this.tintindex;
builder.uvs = this.uvs;
builder.rotation = this.rotation;
- builder.blockLight = this.blockLight;
- builder.skyLight = this.skyLight;
+ builder.lightEmission = this.lightEmission;
builder.hasAmbientOcclusion = this.hasAmbientOcclusion;
return builder;
}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/RootTransformsBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/RootTransformsBuilder.java
index e5e3b485630..cb0ba76ed23 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/RootTransformsBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/RootTransformsBuilder.java
@@ -10,11 +10,11 @@
import com.google.gson.JsonObject;
import com.mojang.math.Transformation;
import net.neoforged.neoforge.common.util.TransformationHelper;
-import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Quaternionfc;
import org.joml.Vector3f;
import org.joml.Vector3fc;
+import org.jspecify.annotations.Nullable;
public class RootTransformsBuilder {
private static final Vector3f ONE = new Vector3f(1, 1, 1);
@@ -23,8 +23,7 @@ public class RootTransformsBuilder {
private Quaternionfc leftRotation = new Quaternionf();
private Quaternionfc rightRotation = new Quaternionf();
private Vector3fc scale = ONE;
- @Nullable
- private TransformationHelper.TransformOrigin origin;
+ private TransformationHelper.@Nullable TransformOrigin origin;
@Nullable
private Vector3fc originVec;
diff --git a/src/client/java/net/neoforged/neoforge/client/model/generators/template/RotationBuilder.java b/src/client/java/net/neoforged/neoforge/client/model/generators/template/RotationBuilder.java
index d9508f09bc0..aa92be85f5b 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/generators/template/RotationBuilder.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/generators/template/RotationBuilder.java
@@ -8,14 +8,13 @@
import com.google.common.base.Preconditions;
import net.minecraft.client.renderer.block.model.BlockElementRotation;
import net.minecraft.core.Direction;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
+import org.jspecify.annotations.Nullable;
public final class RotationBuilder {
@Nullable
private Vector3f origin;
- @Nullable
- private BlockElementRotation.RotationValue value;
+ private BlockElementRotation.@Nullable RotationValue value;
private boolean rescale;
/**
diff --git a/src/client/java/net/neoforged/neoforge/client/model/item/DynamicFluidContainerModel.java b/src/client/java/net/neoforged/neoforge/client/model/item/DynamicFluidContainerModel.java
index eea30d3fad5..0f2d10decb1 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/item/DynamicFluidContainerModel.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/item/DynamicFluidContainerModel.java
@@ -16,6 +16,7 @@
import java.util.Map;
import java.util.Optional;
import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.client.renderer.item.BlockModelWrapper;
@@ -34,20 +35,21 @@
import net.minecraft.world.entity.ItemOwner;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.neoforge.client.ClientHooks;
import net.neoforged.neoforge.client.NeoForgeRenderTypes;
import net.neoforged.neoforge.client.RenderTypeGroup;
+import net.neoforged.neoforge.client.RenderTypeHelper;
import net.neoforged.neoforge.client.color.item.FluidContentsTint;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.client.model.ComposedModelState;
-import net.neoforged.neoforge.client.model.QuadTransformers;
import net.neoforged.neoforge.client.model.UnbakedElementsHelper;
import net.neoforged.neoforge.transfer.fluid.FluidUtil;
-import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
+import org.jspecify.annotations.Nullable;
/**
* A dynamic fluid container model, capable of re-texturing itself at runtime to match the contained fluid.
@@ -60,9 +62,11 @@ public class DynamicFluidContainerModel implements ItemModel {
private static final Transformation FLUID_TRANSFORM = new Transformation(new Vector3f(), new Quaternionf(), new Vector3f(1, 1, 1.002f), new Quaternionf());
private static final Transformation COVER_TRANSFORM = new Transformation(new Vector3f(), new Quaternionf(), new Vector3f(1, 1, 1.004f), new Quaternionf());
private static final ModelDebugName DEBUG_NAME = () -> "DynamicFluidContainerModel";
+ private static final RenderTypeGroup RENDER_TYPES_DEFAULT = new RenderTypeGroup(ChunkSectionLayer.TRANSLUCENT, NeoForgeRenderTypes::getUnsortedTranslucent);
+ private static final RenderTypeGroup RENDER_TYPES_UNLIT = new RenderTypeGroup(ChunkSectionLayer.TRANSLUCENT, NeoForgeRenderTypes::getUnlitTranslucent);
private static RenderTypeGroup getLayerRenderTypes(boolean unlit) {
- return new RenderTypeGroup(ChunkSectionLayer.TRANSLUCENT, unlit ? NeoForgeRenderTypes.ITEM_UNSORTED_UNLIT_TRANSLUCENT.get() : NeoForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get());
+ return unlit ? RENDER_TYPES_UNLIT : RENDER_TYPES_DEFAULT;
}
private final Unbaked unbakedModel;
@@ -114,7 +118,8 @@ private ItemModel bakeModelForFluid(Fluid fluid) {
// Base texture
var unbaked = UnbakedElementsHelper.createUnbakedItemElements(0, baseSprite);
var quads = UnbakedElementsHelper.bakeElements(unbaked, $ -> baseSprite, state);
- subModels.add(new BlockModelWrapper(List.of(), quads, renderProperties, stack -> normalRenderTypes.entity()));
+ var renderType = RenderTypeHelper.detectItemModelRenderType(quads, normalRenderTypes);
+ subModels.add(new BlockModelWrapper(List.of(), quads, renderProperties, renderType));
}
if (fluidMaskLocation != null && fluidSprite != null) {
@@ -125,10 +130,13 @@ private ItemModel bakeModelForFluid(Fluid fluid) {
var quads = UnbakedElementsHelper.bakeElements(unbaked, $ -> fluidSprite, transformedState); // Bake with fluid texture
var emissive = unbakedModel.applyFluidLuminosity && fluid.getFluidType().getLightLevel() > 0;
- var renderTypes = getLayerRenderTypes(emissive);
- if (emissive) QuadTransformers.settingMaxEmissivity().processInPlace(quads);
+ var renderType = RenderTypeHelper.detectItemModelRenderType(quads, getLayerRenderTypes(emissive));
+ if (emissive) {
+ quads = new ArrayList<>(quads);
+ quads.replaceAll(DynamicFluidContainerModel::setMaxEmissivity);
+ }
- subModels.add(new BlockModelWrapper(List.of(FluidContentsTint.INSTANCE), quads, renderProperties, stack -> renderTypes.entity()));
+ subModels.add(new BlockModelWrapper(List.of(FluidContentsTint.INSTANCE), quads, renderProperties, renderType));
}
if (coverSprite != null) {
@@ -137,12 +145,33 @@ private ItemModel bakeModelForFluid(Fluid fluid) {
var transformedState = new ComposedModelState(state, COVER_TRANSFORM);
var unbaked = UnbakedElementsHelper.createUnbakedItemMaskElements(0, coverSprite); // Use cover as mask
var quads = UnbakedElementsHelper.bakeElements(unbaked, $ -> sprite, transformedState); // Bake with selected texture
- subModels.add(new BlockModelWrapper(List.of(), quads, renderProperties, stack -> normalRenderTypes.entity()));
+ var renderType = RenderTypeHelper.detectItemModelRenderType(quads, normalRenderTypes);
+ subModels.add(new BlockModelWrapper(List.of(), quads, renderProperties, renderType));
}
return new CompositeModel(subModels);
}
+ private static BakedQuad setMaxEmissivity(BakedQuad quad) {
+ return new BakedQuad(
+ quad.position0(),
+ quad.position1(),
+ quad.position2(),
+ quad.position3(),
+ quad.packedUV0(),
+ quad.packedUV1(),
+ quad.packedUV2(),
+ quad.packedUV3(),
+ quad.tintIndex(),
+ quad.direction(),
+ quad.sprite(),
+ quad.shade(),
+ Level.MAX_BRIGHTNESS,
+ quad.bakedNormals(),
+ quad.bakedColors(),
+ quad.hasAmbientOcclusion());
+ }
+
@Override
public void update(ItemStackRenderState renderState, ItemStack stack, ItemModelResolver modelResolver, ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable ItemOwner owner, int seed) {
var fluidStack = FluidUtil.getFirstStackContained(stack);
diff --git a/src/client/java/net/neoforged/neoforge/client/model/obj/ObjGeometry.java b/src/client/java/net/neoforged/neoforge/client/model/obj/ObjGeometry.java
index d47acbe2af4..e9301a48fae 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/obj/ObjGeometry.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/obj/ObjGeometry.java
@@ -16,7 +16,6 @@
import java.util.Objects;
import java.util.Set;
import joptsimple.internal.Strings;
-import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -33,9 +32,9 @@
import net.neoforged.neoforge.client.model.NeoForgeModelProperties;
import net.neoforged.neoforge.client.model.pipeline.QuadBakingVertexConsumer;
import org.apache.commons.lang3.tuple.Pair;
-import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import org.joml.Vector4f;
+import org.jspecify.annotations.Nullable;
public class ObjGeometry implements ExtendedUnbakedGeometry {
private static final Vector4f COLOR_WHITE = new Vector4f(1, 1, 1, 1);
@@ -308,10 +307,9 @@ private Pair makeQuad(int[][] indices, int tintIndex, Vect
quadBaker.setSprite(texture);
quadBaker.setTintIndex(tintIndex);
- int uv2 = 0;
if (emissiveAmbient) {
int fakeLight = (int) ((ambientColor.x() + ambientColor.y() + ambientColor.z()) * 15 / 3.0f);
- uv2 = LightTexture.pack(fakeLight, fakeLight);
+ quadBaker.setLightEmission(fakeLight);
quadBaker.setShade(fakeLight == 0 && shadeQuads);
} else {
quadBaker.setShade(shadeQuads);
@@ -346,7 +344,6 @@ private Pair makeQuad(int[][] indices, int tintIndex, Vect
quadBaker.setUv(
texture.getU(texCoord.x),
texture.getV((flipV ? 1 - texCoord.y : texCoord.y)));
- quadBaker.setLight(uv2);
quadBaker.setNormal(normal.x(), normal.y(), normal.z());
if (i == 0) {
quadBaker.setDirection(Direction.getApproximateNearest(normal.x(), normal.y(), normal.z()));
@@ -454,13 +451,12 @@ protected void addNamesRecursively(Set names) {
}
private class ModelMesh {
- @Nullable
- public ObjMaterialLibrary.Material mat;
+ public ObjMaterialLibrary.@Nullable Material mat;
@Nullable
public String smoothingGroup;
public final List faces = Lists.newArrayList();
- public ModelMesh(@Nullable ObjMaterialLibrary.Material currentMat, @Nullable String currentSmoothingGroup) {
+ public ModelMesh(ObjMaterialLibrary.@Nullable Material currentMat, @Nullable String currentSmoothingGroup) {
this.mat = currentMat;
this.smoothingGroup = currentSmoothingGroup;
}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/obj/ObjTokenizer.java b/src/client/java/net/neoforged/neoforge/client/model/obj/ObjTokenizer.java
index 6ce29921574..d4b5adf7392 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/obj/ObjTokenizer.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/obj/ObjTokenizer.java
@@ -14,7 +14,7 @@
import java.util.Arrays;
import java.util.List;
import joptsimple.internal.Strings;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A tokenizer for OBJ and MTL files.
diff --git a/src/client/java/net/neoforged/neoforge/client/model/pipeline/QuadBakingVertexConsumer.java b/src/client/java/net/neoforged/neoforge/client/model/pipeline/QuadBakingVertexConsumer.java
index 68ef8b56cc3..c00da9c91ee 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/pipeline/QuadBakingVertexConsumer.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/pipeline/QuadBakingVertexConsumer.java
@@ -5,18 +5,16 @@
package net.neoforged.neoforge.client.model.pipeline;
-import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormatElement;
import java.util.Arrays;
-import java.util.IdentityHashMap;
-import java.util.Map;
import net.minecraft.client.model.geom.builders.UVPair;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.util.ARGB;
-import net.minecraft.util.Util;
+import net.neoforged.neoforge.client.model.quad.BakedColors;
+import net.neoforged.neoforge.client.model.quad.BakedNormals;
import net.neoforged.neoforge.client.textures.UnitTextureAtlasSprite;
import org.joml.Vector3f;
@@ -29,13 +27,10 @@
* Built quads must be retrieved after building four vertices
*/
public class QuadBakingVertexConsumer implements VertexConsumer {
- private final Map ELEMENT_OFFSETS = Util.make(new IdentityHashMap<>(), map -> {
- for (var element : DefaultVertexFormat.BLOCK.getElements())
- map.put(element, DefaultVertexFormat.BLOCK.getOffset(element) / 4); // Int offset
- });
-
private final Vector3f[] positions = new Vector3f[4];
private final long[] uvs = new long[4];
+ private final int[] normals = new int[4];
+ private final int[] colors = new int[4];
private int vertexIndex = 0;
private boolean building = false;
@@ -65,28 +60,19 @@ public VertexConsumer addVertex(float x, float y, float z) {
@Override
public VertexConsumer setNormal(float x, float y, float z) {
- // TODO 1.21.11: quads can no longer store baked normals
- //int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
- //quadData[offset] = ((int) (x * 127.0f) & 0xFF) |
- // (((int) (y * 127.0f) & 0xFF) << 8) |
- // (((int) (z * 127.0f) & 0xFF) << 16);
+ normals[vertexIndex] = BakedNormals.pack(x, y, z);
return this;
}
@Override
public VertexConsumer setColor(int packedColor) {
- return setColor(ARGB.red(packedColor), ARGB.green(packedColor), ARGB.blue(packedColor), ARGB.alpha(packedColor));
+ colors[vertexIndex] = packedColor;
+ return this;
}
@Override
public VertexConsumer setColor(int r, int g, int b, int a) {
- // TODO 1.21.11: quads can no longer store baked colors
- //int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.COLOR;
- //quadData[offset] = ((a & 0xFF) << 24) |
- // ((b & 0xFF) << 16) |
- // ((g & 0xFF) << 8) |
- // (r & 0xFF);
- return this;
+ return setColor(ARGB.color(a, r, g, b));
}
@Override
@@ -102,9 +88,6 @@ public VertexConsumer setUv1(int u, int v) {
@Override
public VertexConsumer setUv2(int u, int v) {
- // TODO 1.21.11: quads can no longer store baked per-vertex lighting
- //int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.UV2;
- //quadData[offset] = (u & 0xFFFF) | ((v & 0xFFFF) << 16);
return this;
}
@@ -161,6 +144,8 @@ public BakedQuad bakeQuad() {
sprite,
shade,
lightEmission,
+ BakedNormals.of(normals[0], normals[1], normals[2], normals[3]),
+ BakedColors.of(colors[0], colors[1], colors[2], colors[3]),
hasAmbientOcclusion);
clear();
return quad;
@@ -171,7 +156,10 @@ private void clear() {
building = false;
Arrays.setAll(positions, $ -> new Vector3f());
Arrays.fill(uvs, 0L);
+ Arrays.fill(normals, 0);
+ Arrays.fill(colors, 0xFFFFFFFF);
direction = Direction.DOWN;
sprite = UnitTextureAtlasSprite.INSTANCE;
+ lightEmission = 0;
}
}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/quad/BakedColors.java b/src/client/java/net/neoforged/neoforge/client/model/quad/BakedColors.java
new file mode 100644
index 00000000000..ee496e9ee30
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/model/quad/BakedColors.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client.model.quad;
+
+/**
+ * Holds a static color modulator, either for the entire quad or for each vertex, in the ARGB format.
+ *
+ * The stored color value is converted from ARGB to ABGR during buffering.
+ */
+public sealed interface BakedColors {
+ BakedColors DEFAULT = new PerQuad(0xFFFFFFFF);
+
+ int color(int vertex);
+
+ record PerQuad(int color) implements BakedColors {
+ @Override
+ public int color(int vertex) {
+ return color;
+ }
+ }
+
+ record PerVertex(int color0, int color1, int color2, int color3) implements BakedColors {
+ @Override
+ public int color(int vertex) {
+ return switch (vertex) {
+ case 0 -> color0;
+ case 1 -> color1;
+ case 2 -> color2;
+ case 3 -> color3;
+ default -> throw new IndexOutOfBoundsException(vertex);
+ };
+ }
+ }
+
+ static BakedColors of(int color0, int color1, int color2, int color3) {
+ if (color0 == color1 && color0 == color2 && color0 == color3) {
+ return of(color0);
+ }
+ return new PerVertex(color0, color1, color2, color3);
+ }
+
+ static BakedColors of(int color) {
+ return color == 0xFFFFFFFF ? DEFAULT : new PerQuad(color);
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/quad/BakedNormals.java b/src/client/java/net/neoforged/neoforge/client/model/quad/BakedNormals.java
new file mode 100644
index 00000000000..5df4afa66bf
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/model/quad/BakedNormals.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client.model.quad;
+
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import net.minecraft.util.Mth;
+import org.joml.Vector3f;
+import org.joml.Vector3fc;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Holds pre-computed normals, either for the entire quad or for each vertex.
+ *
+ * The normal values are quantized to an integer between -127 and 127, truncated to a byte
+ * and packed into an int, leaving the MSB unused.
+ *
+ * Normals can also be {@linkplain #isUnspecified(int) unspecified}. In that case, rendering will use the normal implied by {@link BakedQuad#direction()},
+ * while a face normal will be computed for the purposes of AO calculations.
+ */
+public sealed interface BakedNormals {
+ BakedNormals UNSPECIFIED = new PerQuad(0);
+
+ /**
+ * {@return The packed normal of the given vertex}
+ * It can also be {@linkplain #isUnspecified(int) unspecified}.
+ *
+ * @see #unpack(int, Vector3f)
+ */
+ int normal(int vertex);
+
+ record PerQuad(int normal) implements BakedNormals {
+ @Override
+ public int normal(int vertex) {
+ return normal;
+ }
+ }
+
+ record PerVertex(int normal0, int normal1, int normal2, int normal3) implements BakedNormals {
+ @Override
+ public int normal(int vertex) {
+ return switch (vertex) {
+ case 0 -> normal0;
+ case 1 -> normal1;
+ case 2 -> normal2;
+ case 3 -> normal3;
+ default -> throw new IndexOutOfBoundsException(vertex);
+ };
+ }
+ }
+
+ /**
+ * @param normal0 The normal of the first vertex, packed using {@link #pack}.
+ * @param normal1 The normal of the second vertex, packed using {@link #pack}.
+ * @param normal2 The normal of the third vertex, packed using {@link #pack}.
+ * @param normal3 The normal of the fourth vertex, packed using {@link #pack}.
+ */
+ static BakedNormals of(int normal0, int normal1, int normal2, int normal3) {
+ if (normal0 == normal1 && normal0 == normal2 && normal0 == normal3) {
+ return of(normal0);
+ }
+ return new PerVertex(normal0, normal1, normal2, normal3);
+ }
+
+ /**
+ * @param normal The face normal, packed using {@link #pack}.
+ */
+ static BakedNormals of(int normal) {
+ return isUnspecified(normal) ? UNSPECIFIED : new PerQuad(normal);
+ }
+
+ /**
+ * {@return a packed representation of the given normal}
+ */
+ static int pack(float x, float y, float z) {
+ int packedx = ((byte) Math.round(x * 127)) & 0xFF;
+ int packedy = ((byte) Math.round(y * 127)) & 0xFF;
+ int packedz = ((byte) Math.round(z * 127)) & 0xFF;
+
+ return packedx | (packedy << 8) | (packedz << 16);
+ }
+
+ /**
+ * {@return a packed representation of the given normal}
+ */
+ static int pack(Vector3fc normal) {
+ return pack(normal.x(), normal.y(), normal.z());
+ }
+
+ /**
+ * {@return the component of the given packed normal}
+ *
+ * @param axis Pass 0 to extract the x component, 1 for y and 2 for z.
+ *
+ * @see #unpackX(int)
+ * @see #unpackY(int)
+ * @see #unpackZ(int)
+ */
+ static float unpackComponent(int packedNormal, int axis) {
+ int encodedNormalComponent = (packedNormal >> (axis * 8)) & 0xFF;
+ // Casting to byte will cast to a signed int.
+ // This is really important, otherwise negative values will lead to above 1.0 normal components.
+ return ((byte) encodedNormalComponent) / 127.0f;
+ }
+
+ /**
+ * {@return the x component of the given packed normal}
+ *
+ * @see #unpackComponent(int, int)
+ */
+ static float unpackX(int packedNormal) {
+ return ((byte) (packedNormal & 0xFF)) / 127.0f;
+ }
+
+ /**
+ * {@return the y component of the given packed normal}
+ *
+ * @see #unpackComponent(int, int)
+ */
+ static float unpackY(int packedNormal) {
+ return ((byte) ((packedNormal >> 8) & 0xFF)) / 127.0f;
+ }
+
+ /**
+ * {@return the z component of the given packed normal}
+ *
+ * @see #unpackComponent(int, int)
+ */
+ static float unpackZ(int packedNormal) {
+ return ((byte) ((packedNormal >> 16) & 0xFF)) / 127.0f;
+ }
+
+ /**
+ * @param destination The vector to unpack the packed normal into, if {@code null}, a new vector will be allocated.
+ * @return The vector that the normal was unpacked into.
+ */
+ static Vector3fc unpack(int packedNormal, @Nullable Vector3f destination) {
+ if (destination == null) {
+ destination = new Vector3f();
+ }
+ return destination.set(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));
+ }
+
+ /**
+ * {@return true if the packed normal represents an unspecified normal}
+ */
+ static boolean isUnspecified(int packedNormal) {
+ return (packedNormal & 0x00FFFFFF) == 0;
+ }
+
+ /**
+ * Computes the packed normal of a quad based on the given vertex positions.
+ *
+ * @return The packed representation of the computed normal.
+ */
+ static int computeQuadNormal(Vector3fc position0, Vector3fc position1, Vector3fc position2, Vector3fc position3) {
+ float dx0 = position3.x() - position1.x();
+ float dy0 = position3.y() - position1.y();
+ float dz0 = position3.z() - position1.z();
+ float dx1 = position2.x() - position0.x();
+ float dy1 = position2.y() - position0.y();
+ float dz1 = position2.z() - position0.z();
+
+ float nx = dy1 * dz0 - dz1 * dy0;
+ float ny = dz1 * dx0 - dx1 * dz0;
+ float nz = dx1 * dy0 - dy1 * dx0;
+
+ float length = Mth.sqrt(nx * nx + ny * ny + nz * nz);
+ if (length > 0) {
+ nx /= length;
+ ny /= length;
+ nz /= length;
+ }
+
+ return pack(nx, ny, nz);
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/quad/QuadTransforms.java b/src/client/java/net/neoforged/neoforge/client/model/quad/QuadTransforms.java
new file mode 100644
index 00000000000..9ed1d214c15
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/model/quad/QuadTransforms.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.client.model.quad;
+
+import com.mojang.math.Transformation;
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import org.joml.Vector3f;
+import org.joml.Vector3fc;
+import org.joml.Vector4f;
+
+public final class QuadTransforms {
+ private QuadTransforms() {}
+
+ /**
+ * Returns a baked quad with the passed transformation applied.
+ */
+ public static BakedQuad applyTransformation(BakedQuad quad, Transformation transformation) {
+ if (transformation.isIdentity()) {
+ return quad;
+ }
+ BakedNormals updatedNormals;
+ if (quad.bakedNormals() == BakedNormals.UNSPECIFIED) {
+ updatedNormals = BakedNormals.UNSPECIFIED;
+ } else {
+ var normalTemp = new Vector3f();
+ updatedNormals = switch (quad.bakedNormals()) {
+ case BakedNormals.PerQuad(int n) -> BakedNormals.of(
+ transformNormal(normalTemp, n, transformation));
+ case BakedNormals.PerVertex(int n0, int n1, int n2, int n3) -> BakedNormals.of(
+ transformNormal(normalTemp, n0, transformation),
+ transformNormal(normalTemp, n1, transformation),
+ transformNormal(normalTemp, n2, transformation),
+ transformNormal(normalTemp, n3, transformation));
+ };
+ }
+ var posTemp = new Vector4f();
+ return new BakedQuad(
+ transformPosition(posTemp, quad.position0(), transformation),
+ transformPosition(posTemp, quad.position1(), transformation),
+ transformPosition(posTemp, quad.position2(), transformation),
+ transformPosition(posTemp, quad.position3(), transformation),
+ quad.packedUV0(),
+ quad.packedUV1(),
+ quad.packedUV2(),
+ quad.packedUV3(),
+ quad.tintIndex(),
+ // TODO: the direction is currently not being transformed, but probably should be
+ quad.direction(),
+ quad.sprite(),
+ quad.shade(),
+ quad.lightEmission(),
+ updatedNormals,
+ quad.bakedColors(),
+ quad.hasAmbientOcclusion());
+ }
+
+ private static Vector3fc transformPosition(Vector4f temp, Vector3fc pos, Transformation transformation) {
+ temp.set(pos.x(), pos.y(), pos.z(), 1);
+ transformation.transformPosition(temp);
+ temp.div(temp.w);
+ return new Vector3f(temp.x(), temp.y(), temp.z());
+ }
+
+ private static int transformNormal(Vector3f temp, int packedNormal, Transformation transformation) {
+ BakedNormals.unpack(packedNormal, temp);
+ transformation.transformNormal(temp);
+ return BakedNormals.pack(temp);
+ }
+}
diff --git a/src/client/java/net/neoforged/neoforge/client/model/quad/package-info.java b/src/client/java/net/neoforged/neoforge/client/model/quad/package-info.java
new file mode 100644
index 00000000000..f290020ced0
--- /dev/null
+++ b/src/client/java/net/neoforged/neoforge/client/model/quad/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) Forge Development LLC and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+@NullMarked
+package net.neoforged.neoforge.client.model.quad;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/client/java/net/neoforged/neoforge/client/model/standalone/StandaloneModelLoader.java b/src/client/java/net/neoforged/neoforge/client/model/standalone/StandaloneModelLoader.java
index 94f344258a0..f37ae54ee9d 100644
--- a/src/client/java/net/neoforged/neoforge/client/model/standalone/StandaloneModelLoader.java
+++ b/src/client/java/net/neoforged/neoforge/client/model/standalone/StandaloneModelLoader.java
@@ -15,7 +15,7 @@
import net.minecraft.util.thread.ParallelMapTransform;
import net.neoforged.fml.ModLoader;
import net.neoforged.neoforge.client.event.ModelEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public final class StandaloneModelLoader {
diff --git a/src/client/java/net/neoforged/neoforge/client/renderstate/BaseRenderState.java b/src/client/java/net/neoforged/neoforge/client/renderstate/BaseRenderState.java
index cbdd40218de..a8afe68d38d 100644
--- a/src/client/java/net/neoforged/neoforge/client/renderstate/BaseRenderState.java
+++ b/src/client/java/net/neoforged/neoforge/client/renderstate/BaseRenderState.java
@@ -11,7 +11,7 @@
import net.minecraft.util.context.ContextKey;
import net.neoforged.neoforge.client.extensions.IRenderStateExtension;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extension class for RenderState objects (ie {@link EntityRenderState}).
diff --git a/src/client/java/net/neoforged/neoforge/client/resources/VanillaClientListeners.java b/src/client/java/net/neoforged/neoforge/client/resources/VanillaClientListeners.java
index 02b398a9186..f5f9aad6442 100644
--- a/src/client/java/net/neoforged/neoforge/client/resources/VanillaClientListeners.java
+++ b/src/client/java/net/neoforged/neoforge/client/resources/VanillaClientListeners.java
@@ -33,7 +33,7 @@
import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent;
import net.neoforged.neoforge.common.util.VanillaClassToKey;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Keys for vanilla {@link PreparableReloadListener reload listeners}, used to specify dependency ordering in the {@link AddClientReloadListenersEvent}.
diff --git a/src/client/java/net/neoforged/neoforge/client/settings/KeyModifier.java b/src/client/java/net/neoforged/neoforge/client/settings/KeyModifier.java
index 4df9265b938..2c8525b1661 100644
--- a/src/client/java/net/neoforged/neoforge/client/settings/KeyModifier.java
+++ b/src/client/java/net/neoforged/neoforge/client/settings/KeyModifier.java
@@ -12,7 +12,7 @@
import net.minecraft.client.Minecraft;
import net.minecraft.client.input.InputQuirks;
import net.minecraft.network.chat.Component;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
public enum KeyModifier {
diff --git a/src/client/java/net/neoforged/neoforge/client/textures/SpriteContentsConstructor.java b/src/client/java/net/neoforged/neoforge/client/textures/SpriteContentsConstructor.java
index e8ce77fa907..442c6fdd9c1 100644
--- a/src/client/java/net/neoforged/neoforge/client/textures/SpriteContentsConstructor.java
+++ b/src/client/java/net/neoforged/neoforge/client/textures/SpriteContentsConstructor.java
@@ -14,7 +14,7 @@
import net.minecraft.client.resources.metadata.texture.TextureMetadataSection;
import net.minecraft.resources.Identifier;
import net.minecraft.server.packs.metadata.MetadataSectionType;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Functional interface representing the signature of the SpriteContents constructor
diff --git a/src/generated/resources/assets/c/lang/en_us.json b/src/generated/resources/assets/c/lang/en_us.json
index 1ad4b7f5c97..2c0cf103808 100644
--- a/src/generated/resources/assets/c/lang/en_us.json
+++ b/src/generated/resources/assets/c/lang/en_us.json
@@ -155,6 +155,10 @@
"tag.fluid.c.water": "Water",
"tag.item.c.animal_foods": "Animal Foods",
"tag.item.c.armors": "Armors",
+ "tag.item.c.armors.horse": "Horse Armors",
+ "tag.item.c.armors.humanoid": "Humanoid Armors",
+ "tag.item.c.armors.nautilus": "Nautilus Armors",
+ "tag.item.c.armors.wolf": "Wolf Armors",
"tag.item.c.barrels": "Barrels",
"tag.item.c.barrels.wooden": "Wooden Barrels",
"tag.item.c.bones": "Bones",
diff --git a/src/generated/resources/data/c/tags/item/armors.json b/src/generated/resources/data/c/tags/item/armors.json
index a1f3ac1ce17..14a7f19912b 100644
--- a/src/generated/resources/data/c/tags/item/armors.json
+++ b/src/generated/resources/data/c/tags/item/armors.json
@@ -1,9 +1,21 @@
{
"values": [
- "#minecraft:head_armor",
- "#minecraft:chest_armor",
- "#minecraft:leg_armor",
- "#minecraft:foot_armor",
+ {
+ "id": "#c:armors/humanoid",
+ "required": false
+ },
+ {
+ "id": "#c:armors/horse",
+ "required": false
+ },
+ {
+ "id": "#c:armors/nautilus",
+ "required": false
+ },
+ {
+ "id": "#c:armors/wolf",
+ "required": false
+ },
{
"id": "#forge:armors",
"required": false
diff --git a/src/generated/resources/data/c/tags/item/armors/horse.json b/src/generated/resources/data/c/tags/item/armors/horse.json
new file mode 100644
index 00000000000..fc121e93aec
--- /dev/null
+++ b/src/generated/resources/data/c/tags/item/armors/horse.json
@@ -0,0 +1,10 @@
+{
+ "values": [
+ "minecraft:leather_horse_armor",
+ "minecraft:copper_horse_armor",
+ "minecraft:iron_horse_armor",
+ "minecraft:golden_horse_armor",
+ "minecraft:diamond_horse_armor",
+ "minecraft:netherite_horse_armor"
+ ]
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/c/tags/item/armors/humanoid.json b/src/generated/resources/data/c/tags/item/armors/humanoid.json
new file mode 100644
index 00000000000..ce638700682
--- /dev/null
+++ b/src/generated/resources/data/c/tags/item/armors/humanoid.json
@@ -0,0 +1,8 @@
+{
+ "values": [
+ "#minecraft:head_armor",
+ "#minecraft:chest_armor",
+ "#minecraft:leg_armor",
+ "#minecraft:foot_armor"
+ ]
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/c/tags/item/armors/nautilus.json b/src/generated/resources/data/c/tags/item/armors/nautilus.json
new file mode 100644
index 00000000000..5188c418ae8
--- /dev/null
+++ b/src/generated/resources/data/c/tags/item/armors/nautilus.json
@@ -0,0 +1,9 @@
+{
+ "values": [
+ "minecraft:copper_nautilus_armor",
+ "minecraft:iron_nautilus_armor",
+ "minecraft:golden_nautilus_armor",
+ "minecraft:diamond_nautilus_armor",
+ "minecraft:netherite_nautilus_armor"
+ ]
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/c/tags/item/armors/wolf.json b/src/generated/resources/data/c/tags/item/armors/wolf.json
new file mode 100644
index 00000000000..1aed8bde945
--- /dev/null
+++ b/src/generated/resources/data/c/tags/item/armors/wolf.json
@@ -0,0 +1,5 @@
+{
+ "values": [
+ "minecraft:wolf_armor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/java/net/neoforged/neoforge/attachment/AttachmentHolder.java b/src/main/java/net/neoforged/neoforge/attachment/AttachmentHolder.java
index bd0a364c77a..5320d2ef4a6 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/AttachmentHolder.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/AttachmentHolder.java
@@ -16,7 +16,7 @@
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/main/java/net/neoforged/neoforge/attachment/AttachmentSync.java b/src/main/java/net/neoforged/neoforge/attachment/AttachmentSync.java
index 6ec83bcd86b..e37eccf2c2c 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/AttachmentSync.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/AttachmentSync.java
@@ -35,7 +35,7 @@
import net.neoforged.neoforge.registries.RegistryBuilder;
import net.neoforged.neoforge.registries.callback.AddCallback;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
@EventBusSubscriber(modid = NeoForgeMod.MOD_ID)
diff --git a/src/main/java/net/neoforged/neoforge/attachment/AttachmentSyncHandler.java b/src/main/java/net/neoforged/neoforge/attachment/AttachmentSyncHandler.java
index 7ceb0a0d191..3b502a994c8 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/AttachmentSyncHandler.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/AttachmentSyncHandler.java
@@ -7,7 +7,7 @@
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Manages how data attachments are written (on the server) and read (on the client) from packets.
diff --git a/src/main/java/net/neoforged/neoforge/attachment/AttachmentType.java b/src/main/java/net/neoforged/neoforge/attachment/AttachmentType.java
index 6f7f6583896..b4c8b0a5f2f 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/AttachmentType.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/AttachmentType.java
@@ -30,7 +30,7 @@
import net.minecraft.world.level.storage.ValueOutput;
import net.neoforged.neoforge.common.util.ValueIOSerializable;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Represents a data attachment type: some data that can be added to any object implementing {@link IAttachmentHolder}.
diff --git a/src/main/java/net/neoforged/neoforge/attachment/IAttachmentCopyHandler.java b/src/main/java/net/neoforged/neoforge/attachment/IAttachmentCopyHandler.java
index 80b47a68420..74e89d270c9 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/IAttachmentCopyHandler.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/IAttachmentCopyHandler.java
@@ -6,7 +6,7 @@
package net.neoforged.neoforge.attachment;
import net.minecraft.core.HolderLookup;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Custom copy handler for data attachments, to improve efficiency compared to the default
diff --git a/src/main/java/net/neoforged/neoforge/attachment/IAttachmentHolder.java b/src/main/java/net/neoforged/neoforge/attachment/IAttachmentHolder.java
index 8e19ccadd6d..bb99428f51e 100644
--- a/src/main/java/net/neoforged/neoforge/attachment/IAttachmentHolder.java
+++ b/src/main/java/net/neoforged/neoforge/attachment/IAttachmentHolder.java
@@ -7,7 +7,7 @@
import java.util.Optional;
import java.util.function.Supplier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* An object that can hold data attachments.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/BaseCapability.java b/src/main/java/net/neoforged/neoforge/capabilities/BaseCapability.java
index 8165de3eef7..95550876360 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/BaseCapability.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/BaseCapability.java
@@ -6,7 +6,7 @@
package net.neoforged.neoforge.capabilities;
import net.minecraft.resources.Identifier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Base class to reuse code common between most/all {@code *Capability} implementation.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/BlockCapability.java b/src/main/java/net/neoforged/neoforge/capabilities/BlockCapability.java
index c45787d3f0d..dbf40c5153f 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/BlockCapability.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/BlockCapability.java
@@ -18,7 +18,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.bus.api.EventPriority;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A {@code BlockCapability} gives flexible access to objects of type {@code T} located in the world.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/BlockCapabilityCache.java b/src/main/java/net/neoforged/neoforge/capabilities/BlockCapabilityCache.java
index a26eee2428d..6337107f0f4 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/BlockCapabilityCache.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/BlockCapabilityCache.java
@@ -10,7 +10,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A cache for block capabilities, to be used to track capabilities at a specific position, with a specific context.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/Capabilities.java b/src/main/java/net/neoforged/neoforge/capabilities/Capabilities.java
index 360f14c48eb..9d41bf6e670 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/Capabilities.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/Capabilities.java
@@ -12,7 +12,7 @@
import net.neoforged.neoforge.transfer.energy.EnergyHandler;
import net.neoforged.neoforge.transfer.fluid.FluidResource;
import net.neoforged.neoforge.transfer.item.ItemResource;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Capabilities provided by NeoForge itself, for modders to directly reference.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/EntityCapability.java b/src/main/java/net/neoforged/neoforge/capabilities/EntityCapability.java
index 62e6885583a..67e05b89cc2 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/EntityCapability.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/EntityCapability.java
@@ -13,7 +13,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* An {@code EntityCapability} gives flexible access to objects of type {@code T} from entities.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/IBlockCapabilityProvider.java b/src/main/java/net/neoforged/neoforge/capabilities/IBlockCapabilityProvider.java
index dfa066fabf7..218148051b8 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/IBlockCapabilityProvider.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/IBlockCapabilityProvider.java
@@ -11,7 +11,7 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@FunctionalInterface
public interface IBlockCapabilityProvider {
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/ICapabilityProvider.java b/src/main/java/net/neoforged/neoforge/capabilities/ICapabilityProvider.java
index a168bb87e7f..147c0e61e6f 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/ICapabilityProvider.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/ICapabilityProvider.java
@@ -7,7 +7,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@FunctionalInterface
public interface ICapabilityProvider {
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/ItemCapability.java b/src/main/java/net/neoforged/neoforge/capabilities/ItemCapability.java
index 15c013d2f7d..79558770a76 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/ItemCapability.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/ItemCapability.java
@@ -12,7 +12,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* An {@code ItemCapability} gives flexible access to objects of type {@code T} from item stacks.
diff --git a/src/main/java/net/neoforged/neoforge/capabilities/RegisterCapabilitiesEvent.java b/src/main/java/net/neoforged/neoforge/capabilities/RegisterCapabilitiesEvent.java
index 9e22853179e..91587e38cad 100644
--- a/src/main/java/net/neoforged/neoforge/capabilities/RegisterCapabilitiesEvent.java
+++ b/src/main/java/net/neoforged/neoforge/capabilities/RegisterCapabilitiesEvent.java
@@ -20,7 +20,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.fml.event.IModBusEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired to register capability providers at an appropriate time.
diff --git a/src/main/java/net/neoforged/neoforge/common/BasicItemListing.java b/src/main/java/net/neoforged/neoforge/common/BasicItemListing.java
index 96587f101ab..36725e7f366 100644
--- a/src/main/java/net/neoforged/neoforge/common/BasicItemListing.java
+++ b/src/main/java/net/neoforged/neoforge/common/BasicItemListing.java
@@ -15,7 +15,7 @@
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.ItemCost;
import net.minecraft.world.item.trading.MerchantOffer;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A default, exposed implementation of ITrade. All of the other implementations of ITrade (in VillagerTrades) are not public.
diff --git a/src/main/java/net/neoforged/neoforge/common/BooleanAttribute.java b/src/main/java/net/neoforged/neoforge/common/BooleanAttribute.java
index faf7277198f..61e875914d1 100644
--- a/src/main/java/net/neoforged/neoforge/common/BooleanAttribute.java
+++ b/src/main/java/net/neoforged/neoforge/common/BooleanAttribute.java
@@ -12,7 +12,7 @@
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation;
import net.minecraft.world.item.TooltipFlag;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A boolean attribute only has two states, on or off, represented by a value of 0 (false) or 1 (true).
diff --git a/src/main/java/net/neoforged/neoforge/common/CommonHooks.java b/src/main/java/net/neoforged/neoforge/common/CommonHooks.java
index 19208576440..e7e733b4c30 100644
--- a/src/main/java/net/neoforged/neoforge/common/CommonHooks.java
+++ b/src/main/java/net/neoforged/neoforge/common/CommonHooks.java
@@ -231,7 +231,7 @@
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.spongepowered.asm.mixin.transformer.meta.MixinMerged;
/**
@@ -1353,8 +1353,7 @@ public static boolean shouldSuppressEnderManAnger(EnderMan enderMan, Player play
/**
* @hidden For internal use only.
*/
- @Nullable
- public static StructuresBecomeConfiguredFix.Conversion getStructureConversion(String originalBiome) {
+ public static StructuresBecomeConfiguredFix.@Nullable Conversion getStructureConversion(String originalBiome) {
return FORGE_CONVERSION_MAP.get().get(originalBiome);
}
diff --git a/src/main/java/net/neoforged/neoforge/common/CreativeModeTabRegistry.java b/src/main/java/net/neoforged/neoforge/common/CreativeModeTabRegistry.java
index 7712c3172d0..c7ed28b36f5 100644
--- a/src/main/java/net/neoforged/neoforge/common/CreativeModeTabRegistry.java
+++ b/src/main/java/net/neoforged/neoforge/common/CreativeModeTabRegistry.java
@@ -41,7 +41,7 @@
import net.neoforged.fml.loading.toposort.TopologicalSort;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public final class CreativeModeTabRegistry {
diff --git a/src/main/java/net/neoforged/neoforge/common/DataMapHooks.java b/src/main/java/net/neoforged/neoforge/common/DataMapHooks.java
index ef644f34151..6134a8423f2 100644
--- a/src/main/java/net/neoforged/neoforge/common/DataMapHooks.java
+++ b/src/main/java/net/neoforged/neoforge/common/DataMapHooks.java
@@ -25,7 +25,7 @@
import net.neoforged.neoforge.registries.datamaps.builtin.Oxidizable;
import net.neoforged.neoforge.registries.datamaps.builtin.Waxable;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
// TODO: 1.21.2 remove fallback to vanilla map for waxing and oxidizing
public class DataMapHooks {
diff --git a/src/main/java/net/neoforged/neoforge/common/IOUtilities.java b/src/main/java/net/neoforged/neoforge/common/IOUtilities.java
index 07d4feb9b0d..7a6583c8a3f 100644
--- a/src/main/java/net/neoforged/neoforge/common/IOUtilities.java
+++ b/src/main/java/net/neoforged/neoforge/common/IOUtilities.java
@@ -23,7 +23,7 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import org.apache.commons.io.output.CloseShieldOutputStream;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/net/neoforged/neoforge/common/IShearable.java b/src/main/java/net/neoforged/neoforge/common/IShearable.java
index 8fe239636ea..81142386476 100644
--- a/src/main/java/net/neoforged/neoforge/common/IShearable.java
+++ b/src/main/java/net/neoforged/neoforge/common/IShearable.java
@@ -25,7 +25,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This interfaces allows shears (modded & vanilla) and {@linkplain Entity entities} (modded & vanilla) to cooperate
diff --git a/src/main/java/net/neoforged/neoforge/common/ModConfigSpec.java b/src/main/java/net/neoforged/neoforge/common/ModConfigSpec.java
index df549a1b5f9..51113fd49ee 100644
--- a/src/main/java/net/neoforged/neoforge/common/ModConfigSpec.java
+++ b/src/main/java/net/neoforged/neoforge/common/ModConfigSpec.java
@@ -47,7 +47,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/*
* Like {@link com.electronwill.nightconfig.core.ConfigSpec} except in builder format, and extended to accept comments, language keys,
diff --git a/src/main/java/net/neoforged/neoforge/common/MutableDataComponentHolder.java b/src/main/java/net/neoforged/neoforge/common/MutableDataComponentHolder.java
index 195a09efc2b..be2de595c24 100644
--- a/src/main/java/net/neoforged/neoforge/common/MutableDataComponentHolder.java
+++ b/src/main/java/net/neoforged/neoforge/common/MutableDataComponentHolder.java
@@ -13,7 +13,7 @@
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface MutableDataComponentHolder extends DataComponentHolder {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java
index 06c905feba4..70f3ec36646 100644
--- a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java
+++ b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java
@@ -34,6 +34,8 @@
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.random.Weighted;
import net.minecraft.util.random.WeightedList;
+import net.minecraft.world.attribute.AttributeType;
+import net.minecraft.world.attribute.EnvironmentAttribute;
import net.minecraft.world.attribute.EnvironmentAttributes;
import net.minecraft.world.damagesource.DamageSources;
import net.minecraft.world.damagesource.DamageType;
@@ -119,6 +121,8 @@
import net.neoforged.neoforge.common.world.BiomeModifiers.AddSpawnsBiomeModifier;
import net.neoforged.neoforge.common.world.BiomeModifiers.RemoveFeaturesBiomeModifier;
import net.neoforged.neoforge.common.world.BiomeModifiers.RemoveSpawnsBiomeModifier;
+import net.neoforged.neoforge.common.world.NeoForgeAttributeTypes;
+import net.neoforged.neoforge.common.world.NeoForgeEnvironmentAttributes;
import net.neoforged.neoforge.common.world.NoneBiomeModifier;
import net.neoforged.neoforge.common.world.NoneStructureModifier;
import net.neoforged.neoforge.common.world.StructureModifier;
@@ -162,7 +166,7 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@SuppressWarnings("unused")
@Mod(NeoForgeMod.MOD_ID)
@@ -182,6 +186,8 @@ public class NeoForgeMod {
private static final DeferredRegister> BIOME_MODIFIER_SERIALIZERS = DeferredRegister.create(NeoForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, MOD_ID);
private static final DeferredRegister> STRUCTURE_MODIFIER_SERIALIZERS = DeferredRegister.create(NeoForgeRegistries.Keys.STRUCTURE_MODIFIER_SERIALIZERS, MOD_ID);
private static final DeferredRegister HOLDER_SET_TYPES = DeferredRegister.create(NeoForgeRegistries.Keys.HOLDER_SET_TYPES, MOD_ID);
+ private static final DeferredRegister> ATTRIBUTE_TYPES = DeferredRegister.create(Registries.ATTRIBUTE_TYPE, MOD_ID);
+ private static final DeferredRegister> ENVIRONMENT_ATTRIBUTES = DeferredRegister.create(Registries.ENVIRONMENT_ATTRIBUTE, MOD_ID);
@SuppressWarnings({ "unchecked", "rawtypes" }) // Uses Holder instead of DeferredHolder as the type due to weirdness between ECJ and javac.
private static final Holder> ENUM_COMMAND_ARGUMENT_TYPE = COMMAND_ARGUMENT_TYPES.register("enum", () -> ArgumentTypeInfos.registerByClass(EnumArgument.class, new EnumArgument.Info()));
@@ -545,6 +551,12 @@ public NeoForgeMod(IEventBus modEventBus, Dist dist, ModContainer container) {
CrashReportCallables.registerCrashCallable("FML", FMLVersion::getVersion);
CrashReportCallables.registerCrashCallable("NeoForge", NeoForgeVersion::getVersion);
+ // Register environment attributes and types
+ ATTRIBUTE_TYPES.register("identifier", () -> NeoForgeAttributeTypes.IDENTIFIER);
+ ENVIRONMENT_ATTRIBUTES.register("custom_weather_effects", () -> NeoForgeEnvironmentAttributes.CUSTOM_WEATHER_EFFECTS);
+ ENVIRONMENT_ATTRIBUTES.register("custom_clouds", () -> NeoForgeEnvironmentAttributes.CUSTOM_CLOUDS);
+ ENVIRONMENT_ATTRIBUTES.register("custom_skybox", () -> NeoForgeEnvironmentAttributes.CUSTOM_SKYBOX);
+
// Forge-provided datapack registries
modEventBus.addListener((DataPackRegistryEvent.NewRegistry event) -> {
event.dataPackRegistry(NeoForgeRegistries.Keys.BIOME_MODIFIERS, BiomeModifier.DIRECT_CODEC);
@@ -570,6 +582,8 @@ public NeoForgeMod(IEventBus modEventBus, Dist dist, ModContainer container) {
FLUID_INGREDIENT_TYPES.register(modEventBus);
CONDITION_CODECS.register(modEventBus);
GLOBAL_LOOT_MODIFIER_SERIALIZERS.register(modEventBus);
+ ATTRIBUTE_TYPES.register(modEventBus);
+ ENVIRONMENT_ATTRIBUTES.register(modEventBus);
NeoForge.EVENT_BUS.addListener(this::serverStopping);
ConfigSync.registerEventListeners();
container.registerConfig(ModConfig.Type.SERVER, NeoForgeServerConfig.SPEC);
diff --git a/src/main/java/net/neoforged/neoforge/common/SpecialPlantable.java b/src/main/java/net/neoforged/neoforge/common/SpecialPlantable.java
index 399bdc0e712..ffff78a8ba3 100644
--- a/src/main/java/net/neoforged/neoforge/common/SpecialPlantable.java
+++ b/src/main/java/net/neoforged/neoforge/common/SpecialPlantable.java
@@ -11,7 +11,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Intended for mods to help mark if a modded item allows for placing modded plants of any kind or size.
diff --git a/src/main/java/net/neoforged/neoforge/common/Tags.java b/src/main/java/net/neoforged/neoforge/common/Tags.java
index 152eea5791b..435758cc08f 100644
--- a/src/main/java/net/neoforged/neoforge/common/Tags.java
+++ b/src/main/java/net/neoforged/neoforge/common/Tags.java
@@ -983,9 +983,26 @@ public static class Items {
*/
public static final TagKey- MINING_TOOL_TOOLS = tag("tools/mining_tool");
/**
- * Collects the 4 vanilla armor tags into one parent collection for ease.
+ * A tag containing all conventional armor tags.
+ * Note that this can contain armor that does not necessarily fit on a player. For that, see {@link Tags.Items#ARMORS_HUMANOID}
*/
public static final TagKey
- ARMORS = tag("armors");
+ /**
+ * Armor that can fit on a humanoid mob like the Player. This tag collects the 4 vanilla armor tags into one parent collection for ease.
+ */
+ public static final TagKey
- ARMORS_HUMANOID = tag("armors/humanoid");
+ /**
+ * A tag containing armor that can fit on a Horse.
+ */
+ public static final TagKey
- ARMORS_HORSE = tag("armors/horse");
+ /**
+ * A tag containing armor that can fit on a Nautilus.
+ */
+ public static final TagKey
- ARMORS_NAUTILUS = tag("armors/nautilus");
+ /**
+ * A tag containing armor that can fit on a Wolf.
+ */
+ public static final TagKey
- ARMORS_WOLF = tag("armors/wolf");
/**
* Collects the many enchantable tags into one parent collection for ease.
*/
diff --git a/src/main/java/net/neoforged/neoforge/common/UsernameCache.java b/src/main/java/net/neoforged/neoforge/common/UsernameCache.java
index 35011f0905d..160a76a3324 100644
--- a/src/main/java/net/neoforged/neoforge/common/UsernameCache.java
+++ b/src/main/java/net/neoforged/neoforge/common/UsernameCache.java
@@ -26,7 +26,7 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Caches player's last known usernames
diff --git a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/PiglinNeutralArmorEntityPredicate.java b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/PiglinNeutralArmorEntityPredicate.java
index b1e333a75d0..077c36229cf 100644
--- a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/PiglinNeutralArmorEntityPredicate.java
+++ b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/PiglinNeutralArmorEntityPredicate.java
@@ -14,7 +14,7 @@
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class PiglinNeutralArmorEntityPredicate implements EntitySubPredicate {
public static final PiglinNeutralArmorEntityPredicate INSTANCE = new PiglinNeutralArmorEntityPredicate();
diff --git a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/SnowBootsEntityPredicate.java b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/SnowBootsEntityPredicate.java
index 055c87beff7..2a1e7dd1e0b 100644
--- a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/SnowBootsEntityPredicate.java
+++ b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/SnowBootsEntityPredicate.java
@@ -12,7 +12,7 @@
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class SnowBootsEntityPredicate implements EntitySubPredicate {
public static final SnowBootsEntityPredicate INSTANCE = new SnowBootsEntityPredicate();
diff --git a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/TridentEntityPredicate.java b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/TridentEntityPredicate.java
index c7841d87397..6bb661fb328 100644
--- a/src/main/java/net/neoforged/neoforge/common/advancements/critereon/TridentEntityPredicate.java
+++ b/src/main/java/net/neoforged/neoforge/common/advancements/critereon/TridentEntityPredicate.java
@@ -11,7 +11,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.arrow.ThrownTrident;
import net.minecraft.world.phys.Vec3;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class TridentEntityPredicate implements EntitySubPredicate {
public static final TridentEntityPredicate INSTANCE = new TridentEntityPredicate();
diff --git a/src/main/java/net/neoforged/neoforge/common/crafting/BlockTagIngredient.java b/src/main/java/net/neoforged/neoforge/common/crafting/BlockTagIngredient.java
index a99a2f17576..6afb6fcc634 100644
--- a/src/main/java/net/neoforged/neoforge/common/crafting/BlockTagIngredient.java
+++ b/src/main/java/net/neoforged/neoforge/common/crafting/BlockTagIngredient.java
@@ -21,7 +21,7 @@
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.common.NeoForgeMod;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* {@link Ingredient} that matches {@link ItemStack}s of {@link Block}s from a {@link TagKey}, useful in cases
diff --git a/src/main/java/net/neoforged/neoforge/common/crafting/ConditionalRecipeOutput.java b/src/main/java/net/neoforged/neoforge/common/crafting/ConditionalRecipeOutput.java
index ad522261d92..1fbaf7764ee 100644
--- a/src/main/java/net/neoforged/neoforge/common/crafting/ConditionalRecipeOutput.java
+++ b/src/main/java/net/neoforged/neoforge/common/crafting/ConditionalRecipeOutput.java
@@ -13,7 +13,7 @@
import net.neoforged.neoforge.common.conditions.ICondition;
import org.apache.commons.lang3.ArrayUtils;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Wrapper around a {@link RecipeOutput} that adds conditions to all received recipes.
diff --git a/src/main/java/net/neoforged/neoforge/common/damagesource/IDeathMessageProvider.java b/src/main/java/net/neoforged/neoforge/common/damagesource/IDeathMessageProvider.java
index e655132f419..b5657025a85 100644
--- a/src/main/java/net/neoforged/neoforge/common/damagesource/IDeathMessageProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/damagesource/IDeathMessageProvider.java
@@ -12,7 +12,7 @@
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DeathMessageType;
import net.minecraft.world.entity.LivingEntity;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* An {@link IDeathMessageProvider} is used by custom {@link DeathMessageType} instances.
diff --git a/src/main/java/net/neoforged/neoforge/common/data/SoundDefinition.java b/src/main/java/net/neoforged/neoforge/common/data/SoundDefinition.java
index 446ba7be1bb..f260f066ce3 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/SoundDefinition.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/SoundDefinition.java
@@ -13,7 +13,7 @@
import java.util.Arrays;
import java.util.List;
import net.minecraft.resources.Identifier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Contains all the data to completely define a sound event.
diff --git a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeAdvancementProvider.java b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeAdvancementProvider.java
index 454cdc4d3a5..f4d00ed293d 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeAdvancementProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeAdvancementProvider.java
@@ -67,7 +67,7 @@
import net.neoforged.neoforge.common.advancements.critereon.PiglinNeutralArmorEntityPredicate;
import net.neoforged.neoforge.common.advancements.critereon.SnowBootsEntityPredicate;
import net.neoforged.neoforge.common.advancements.critereon.TridentEntityPredicate;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class NeoForgeAdvancementProvider extends AdvancementProvider {
public NeoForgeAdvancementProvider(PackOutput output, CompletableFuture registries) {
@@ -333,9 +333,8 @@ public Optional> get(TagKey tagKey) {
});
}
- @Nullable
@SuppressWarnings("removal")
- private Advancement.Builder findAndReplaceInHolder(AdvancementHolder advancementHolder, HolderLookup.Provider registries) {
+ private Advancement.@Nullable Builder findAndReplaceInHolder(AdvancementHolder advancementHolder, HolderLookup.Provider registries) {
Advancement advancement = advancementHolder.value();
Advancement.Builder builder = Advancement.Builder.advancement();
boolean hasReplaced = false;
diff --git a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeItemTagsProvider.java b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeItemTagsProvider.java
index aa861fbc0fd..0fcd96eaec9 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeItemTagsProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeItemTagsProvider.java
@@ -314,7 +314,33 @@ public void addTags(HolderLookup.Provider lookupProvider) {
Tags.Items.TOOLS_IGNITER, Tags.Items.TOOLS_SHEAR, Tags.Items.TOOLS_SHIELD, Tags.Items.TOOLS_SPEAR,
Tags.Items.TOOLS_MACE, Tags.Items.TOOLS_WRENCH,
Tags.Items.MINING_TOOL_TOOLS, Tags.Items.MELEE_WEAPON_TOOLS, Tags.Items.RANGED_WEAPON_TOOLS);
- tag(Tags.Items.ARMORS).addTags(ItemTags.HEAD_ARMOR, ItemTags.CHEST_ARMOR, ItemTags.LEG_ARMOR, ItemTags.FOOT_ARMOR);
+ tag(Tags.Items.ARMORS)
+ .addOptionalTag(Tags.Items.ARMORS_HUMANOID)
+ .addOptionalTag(Tags.Items.ARMORS_HORSE)
+ .addOptionalTag(Tags.Items.ARMORS_NAUTILUS)
+ .addOptionalTag(Tags.Items.ARMORS_WOLF);
+
+ tag(Tags.Items.ARMORS_HORSE)
+ .add(Items.LEATHER_HORSE_ARMOR)
+ .add(Items.COPPER_HORSE_ARMOR)
+ .add(Items.IRON_HORSE_ARMOR)
+ .add(Items.GOLDEN_HORSE_ARMOR)
+ .add(Items.DIAMOND_HORSE_ARMOR)
+ .add(Items.NETHERITE_HORSE_ARMOR);
+
+ tag(Tags.Items.ARMORS_NAUTILUS)
+ .add(Items.COPPER_NAUTILUS_ARMOR)
+ .add(Items.IRON_NAUTILUS_ARMOR)
+ .add(Items.GOLDEN_NAUTILUS_ARMOR)
+ .add(Items.DIAMOND_NAUTILUS_ARMOR)
+ .add(Items.NETHERITE_NAUTILUS_ARMOR);
+
+ tag(Tags.Items.ARMORS_WOLF)
+ .add(Items.WOLF_ARMOR);
+
+ tag(Tags.Items.ARMORS_HUMANOID)
+ .addTags(ItemTags.HEAD_ARMOR, ItemTags.CHEST_ARMOR, ItemTags.LEG_ARMOR, ItemTags.FOOT_ARMOR);
+
tag(Tags.Items.ENCHANTABLES).addTags(ItemTags.ARMOR_ENCHANTABLE, ItemTags.EQUIPPABLE_ENCHANTABLE, ItemTags.WEAPON_ENCHANTABLE, ItemTags.MELEE_WEAPON_ENCHANTABLE, ItemTags.SHARP_WEAPON_ENCHANTABLE, ItemTags.SWEEPING_ENCHANTABLE, ItemTags.MINING_ENCHANTABLE, ItemTags.MINING_LOOT_ENCHANTABLE, ItemTags.FISHING_ENCHANTABLE, ItemTags.TRIDENT_ENCHANTABLE, ItemTags.BOW_ENCHANTABLE, ItemTags.CROSSBOW_ENCHANTABLE, ItemTags.MACE_ENCHANTABLE, ItemTags.FIRE_ASPECT_ENCHANTABLE, ItemTags.DURABILITY_ENCHANTABLE, ItemTags.VANISHING_ENCHANTABLE);
// Backwards compat with pre-1.21 tags. Done after so optional tag is last for better readability.
diff --git a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLanguageProvider.java b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLanguageProvider.java
index d37c8acd999..097661b8d0c 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLanguageProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLanguageProvider.java
@@ -386,6 +386,10 @@ protected void addTranslations() {
add(Tags.Items.MINING_TOOL_TOOLS, "Mining Tools");
add(Tags.Items.TOOLS, "Tools");
add(Tags.Items.ARMORS, "Armors");
+ add(Tags.Items.ARMORS_HUMANOID, "Humanoid Armors");
+ add(Tags.Items.ARMORS_HORSE, "Horse Armors");
+ add(Tags.Items.ARMORS_NAUTILUS, "Nautilus Armors");
+ add(Tags.Items.ARMORS_WOLF, "Wolf Armors");
add(Tags.Items.ENCHANTABLES, "Enchantables");
// Fluids
diff --git a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLootTableProvider.java b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLootTableProvider.java
index 37c4645cb56..d2ecac545a4 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLootTableProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeLootTableProvider.java
@@ -52,7 +52,7 @@
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import net.neoforged.neoforge.common.ItemAbilities;
import net.neoforged.neoforge.common.loot.CanItemPerformAbility;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Currently used only for replacing shears item to shears_dig item ability
@@ -96,8 +96,7 @@ private void replaceLootItemCondition(Function randomSequence = getPrivateValue(LootTable.class, lootTable, "randomSequence");
diff --git a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeRecipeProvider.java b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeRecipeProvider.java
index 4c96523d4ed..905bef9a4c9 100644
--- a/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeRecipeProvider.java
+++ b/src/main/java/net/neoforged/neoforge/common/data/internal/NeoForgeRecipeProvider.java
@@ -38,7 +38,7 @@
import net.neoforged.neoforge.common.Tags;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.crafting.DifferenceIngredient;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public final class NeoForgeRecipeProvider extends VanillaRecipeProvider {
private final InterceptingRecipeOutput output;
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IAttributeExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IAttributeExtension.java
index 5236c77f0f2..9cbcf28363d 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IAttributeExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IAttributeExtension.java
@@ -26,7 +26,7 @@
import net.neoforged.neoforge.common.NeoForgeMod;
import net.neoforged.neoforge.common.config.NeoForgeCommonConfig;
import net.neoforged.neoforge.common.util.AttributeUtil;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IAttributeExtension {
public static final DecimalFormat FORMAT = Util.make(new DecimalFormat("#.##"), fmt -> fmt.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));;
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IBaseRailBlockExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IBaseRailBlockExtension.java
index 40e3563ab1a..9d90ada040b 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IBaseRailBlockExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IBaseRailBlockExtension.java
@@ -12,7 +12,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RailShape;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IBaseRailBlockExtension {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockExtension.java
index 5e3ea31036f..3c063b8074b 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockExtension.java
@@ -82,7 +82,7 @@
import net.neoforged.neoforge.common.world.AuxiliaryLightManager;
import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.model.data.ModelData;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@SuppressWarnings("deprecation")
public interface IBlockExtension {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockGetterExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockGetterExtension.java
index b7f0be42d14..904e37673db 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockGetterExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockGetterExtension.java
@@ -16,7 +16,7 @@
import net.neoforged.neoforge.common.world.AuxiliaryLightManager;
import net.neoforged.neoforge.model.data.ModelData;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IBlockGetterExtension {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockStateExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockStateExtension.java
index 8400ff2ffc4..096ebcec99c 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IBlockStateExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IBlockStateExtension.java
@@ -46,7 +46,7 @@
import net.neoforged.neoforge.common.enums.BubbleColumnDirection;
import net.neoforged.neoforge.common.world.AuxiliaryLightManager;
import net.neoforged.neoforge.event.EventHooks;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IBlockStateExtension {
private BlockState self() {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/ICommandSourceStackExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/ICommandSourceStackExtension.java
index b23fc6e922b..4ccfcd07527 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/ICommandSourceStackExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/ICommandSourceStackExtension.java
@@ -10,7 +10,7 @@
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.Level;
import net.minecraft.world.scores.Scoreboard;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Additional methods for {@link CommandSourceStack} so that commands and arguments can access various things without directly referencing using server specific classes
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IDataComponentMapBuilderExtensions.java b/src/main/java/net/neoforged/neoforge/common/extensions/IDataComponentMapBuilderExtensions.java
index 7fbbfab31d2..cb3ab8f9407 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IDataComponentMapBuilderExtensions.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IDataComponentMapBuilderExtensions.java
@@ -8,7 +8,7 @@
import java.util.function.Supplier;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentType;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IDataComponentMapBuilderExtensions {
private DataComponentMap.Builder self() {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IDispensibleContainerItemExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IDispensibleContainerItemExtension.java
index 7860a4d0595..f9eca8bd8e0 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IDispensibleContainerItemExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IDispensibleContainerItemExtension.java
@@ -11,7 +11,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IDispensibleContainerItemExtension {
private DispensibleContainerItem self() {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IEntityExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IEntityExtension.java
index eb506a2132e..b44e6c956a5 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IEntityExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IEntityExtension.java
@@ -30,7 +30,7 @@
import net.neoforged.neoforge.entity.PartEntity;
import net.neoforged.neoforge.fluids.FluidType;
import net.neoforged.neoforge.network.payload.AdvancedAddEntityPayload;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IEntityExtension {
private Entity self() {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IFluidExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IFluidExtension.java
index 5bb188640cc..e66f06a1167 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IFluidExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IFluidExtension.java
@@ -18,7 +18,7 @@
import net.minecraft.world.level.pathfinder.PathType;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.fluids.FluidType;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IFluidExtension {
private Fluid self() {
@@ -100,7 +100,7 @@ default boolean supportsBoating(FluidState state, AbstractBoat boat) {
* @return the path type of this fluid
*/
@Nullable
- default PathType getBlockPathType(FluidState state, BlockGetter level, BlockPos pos, @org.jetbrains.annotations.Nullable Mob mob, boolean canFluidLog) {
+ default PathType getBlockPathType(FluidState state, BlockGetter level, BlockPos pos, @org.jspecify.annotations.Nullable Mob mob, boolean canFluidLog) {
return getFluidType().getBlockPathType(state, level, pos, mob, canFluidLog);
}
@@ -118,7 +118,7 @@ default PathType getBlockPathType(FluidState state, BlockGetter level, BlockPos
* @return the path type of this fluid
*/
@Nullable
- default PathType getAdjacentBlockPathType(FluidState state, BlockGetter level, BlockPos pos, @org.jetbrains.annotations.Nullable Mob mob, PathType originalType) {
+ default PathType getAdjacentBlockPathType(FluidState state, BlockGetter level, BlockPos pos, @org.jspecify.annotations.Nullable Mob mob, PathType originalType) {
return getFluidType().getAdjacentBlockPathType(state, level, pos, mob, originalType);
}
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IFluidStateExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IFluidStateExtension.java
index f78672595b3..c1c7f3cf8d9 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IFluidStateExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IFluidStateExtension.java
@@ -17,7 +17,7 @@
import net.minecraft.world.level.pathfinder.PathType;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.fluids.FluidType;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IFluidStateExtension {
private FluidState self() {
@@ -92,7 +92,7 @@ default boolean supportsBoating(AbstractBoat boat) {
* @return the path type of this fluid
*/
@Nullable
- default PathType getBlockPathType(BlockGetter level, BlockPos pos, @org.jetbrains.annotations.Nullable Mob mob, boolean canFluidLog) {
+ default PathType getBlockPathType(BlockGetter level, BlockPos pos, @org.jspecify.annotations.Nullable Mob mob, boolean canFluidLog) {
return self().getType().getBlockPathType(self(), level, pos, mob, canFluidLog);
}
@@ -109,7 +109,7 @@ default PathType getBlockPathType(BlockGetter level, BlockPos pos, @org.jetbrain
* @return the path type of this fluid
*/
@Nullable
- default PathType getAdjacentBlockPathType(BlockGetter level, BlockPos pos, @org.jetbrains.annotations.Nullable Mob mob, PathType originalType) {
+ default PathType getAdjacentBlockPathType(BlockGetter level, BlockPos pos, @org.jspecify.annotations.Nullable Mob mob, PathType originalType) {
return self().getType().getAdjacentBlockPathType(self(), level, pos, mob, originalType);
}
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IHolderExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IHolderExtension.java
index efdb5176155..cfb5863196e 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IHolderExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IHolderExtension.java
@@ -10,7 +10,7 @@
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.neoforged.neoforge.registries.datamaps.IWithData;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extension for {@link Holder}
@@ -30,8 +30,7 @@ default Holder getDelegate() {
*
* This will only succeed if the underlying holder is a {@link Holder.Reference}.
*/
- @Nullable
- default HolderLookup.RegistryLookup unwrapLookup() {
+ default HolderLookup.@Nullable RegistryLookup unwrapLookup() {
return null;
}
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IItemExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IItemExtension.java
index 261af274e0b..477565a6706 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IItemExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IItemExtension.java
@@ -51,7 +51,7 @@
import net.neoforged.neoforge.common.ItemAbilities;
import net.neoforged.neoforge.common.ItemAbility;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IItemExtension {
private Item self() {
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IItemStackExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IItemStackExtension.java
index a8e63b693a4..249d073f3ab 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IItemStackExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IItemStackExtension.java
@@ -41,7 +41,7 @@
import net.neoforged.neoforge.common.ItemAbility;
import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/*
* Extension added to ItemStack that bounces to ItemSack sensitive Item methods. Typically this is just for convince.
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/ILevelExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/ILevelExtension.java
index 580865cde63..51876e9f685 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/ILevelExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/ILevelExtension.java
@@ -14,7 +14,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.capabilities.BlockCapability;
import net.neoforged.neoforge.model.data.ModelDataManager;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface ILevelExtension {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IOwnedSpawner.java b/src/main/java/net/neoforged/neoforge/common/extensions/IOwnedSpawner.java
index dcc2f986d40..36b2cd64971 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IOwnedSpawner.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IOwnedSpawner.java
@@ -12,7 +12,7 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public interface IOwnedSpawner {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IRecipeOutputExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IRecipeOutputExtension.java
index 541263baaf0..2989c600770 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IRecipeOutputExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IRecipeOutputExtension.java
@@ -11,7 +11,7 @@
import net.minecraft.world.item.crafting.Recipe;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.crafting.ConditionalRecipeOutput;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extra methods for {@link RecipeOutput}.
diff --git a/src/main/java/net/neoforged/neoforge/common/extensions/IServerCommonPacketListenerExtension.java b/src/main/java/net/neoforged/neoforge/common/extensions/IServerCommonPacketListenerExtension.java
index 7a6d33e0592..fb2bfbf5c1f 100644
--- a/src/main/java/net/neoforged/neoforge/common/extensions/IServerCommonPacketListenerExtension.java
+++ b/src/main/java/net/neoforged/neoforge/common/extensions/IServerCommonPacketListenerExtension.java
@@ -10,7 +10,7 @@
import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
import net.minecraft.network.protocol.common.ServerCommonPacketListener;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extension interface for {@link ServerCommonPacketListener}
diff --git a/src/main/java/net/neoforged/neoforge/common/ticket/SimpleTicket.java b/src/main/java/net/neoforged/neoforge/common/ticket/SimpleTicket.java
index fbc9e1b6c77..15aa00d4813 100644
--- a/src/main/java/net/neoforged/neoforge/common/ticket/SimpleTicket.java
+++ b/src/main/java/net/neoforged/neoforge/common/ticket/SimpleTicket.java
@@ -8,7 +8,7 @@
import com.google.common.base.Preconditions;
import java.util.function.Consumer;
import net.neoforged.neoforge.common.FarmlandWaterManager;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Common class for a simple ticket based system.
diff --git a/src/main/java/net/neoforged/neoforge/common/util/AttributeTooltipContext.java b/src/main/java/net/neoforged/neoforge/common/util/AttributeTooltipContext.java
index fc2ca7ddb8a..5f96b07d268 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/AttributeTooltipContext.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/AttributeTooltipContext.java
@@ -14,7 +14,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Extended {@link TooltipContext} used when generating attribute tooltips.
diff --git a/src/main/java/net/neoforged/neoforge/common/util/BlockSnapshot.java b/src/main/java/net/neoforged/neoforge/common/util/BlockSnapshot.java
index 3ec5caa589a..8dd74ca6d01 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/BlockSnapshot.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/BlockSnapshot.java
@@ -22,7 +22,7 @@
import net.minecraft.world.level.storage.TagValueInput;
import net.neoforged.neoforge.event.level.BlockEvent;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/util/FakePlayer.java b/src/main/java/net/neoforged/neoforge/common/util/FakePlayer.java
index 67d95face39..d31952b4372 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/FakePlayer.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/FakePlayer.java
@@ -10,7 +10,6 @@
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Consumer;
-import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.PacketListener;
import net.minecraft.network.RegistryFriendlyByteBuf;
@@ -80,7 +79,7 @@
import net.minecraft.world.entity.Relative;
import net.minecraft.world.entity.animal.equine.AbstractHorse;
import net.minecraft.world.entity.player.Player;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A basic fake server player implementation that can be used to simulate player actions.
@@ -130,7 +129,6 @@ public boolean isFakePlayer() {
return true;
}
- @ParametersAreNonnullByDefault
private static class FakePlayerNetHandler extends ServerGamePacketListenerImpl {
private static final net.minecraft.network.Connection DUMMY_CONNECTION = new FakeConnection();
diff --git a/src/main/java/net/neoforged/neoforge/common/util/JsonUtils.java b/src/main/java/net/neoforged/neoforge/common/util/JsonUtils.java
index fdb357d3a68..667b4ea5e0f 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/JsonUtils.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/JsonUtils.java
@@ -24,7 +24,7 @@
import java.util.Map;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class JsonUtils {
// http://stackoverflow.com/questions/7706772/deserializing-immutablelist-using-gson/21677349#21677349
diff --git a/src/main/java/net/neoforged/neoforge/common/util/Lazy.java b/src/main/java/net/neoforged/neoforge/common/util/Lazy.java
index dccc2cc320f..3dfcfe31cc2 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/Lazy.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/Lazy.java
@@ -6,7 +6,7 @@
package net.neoforged.neoforge.common.util;
import java.util.function.Supplier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Proxy object for a value that is calculated on first access, and can be refreshed as well.
diff --git a/src/main/java/net/neoforged/neoforge/common/util/MutableHashedLinkedMap.java b/src/main/java/net/neoforged/neoforge/common/util/MutableHashedLinkedMap.java
index 84e6da496a1..33798b88029 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/MutableHashedLinkedMap.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/MutableHashedLinkedMap.java
@@ -13,7 +13,7 @@
import java.util.NoSuchElementException;
import java.util.function.BiPredicate;
import net.neoforged.neoforge.common.util.strategy.BasicStrategy;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A mutable linked map with a hashing strategy and a merge function.
diff --git a/src/main/java/net/neoforged/neoforge/common/util/RecipeMatcher.java b/src/main/java/net/neoforged/neoforge/common/util/RecipeMatcher.java
index dcf2cebaff8..3e130c2705c 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/RecipeMatcher.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/RecipeMatcher.java
@@ -11,7 +11,7 @@
import java.util.List;
import java.util.Queue;
import java.util.function.Predicate;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class RecipeMatcher {
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/util/Size2i.java b/src/main/java/net/neoforged/neoforge/common/util/Size2i.java
index 863378508b8..0c4d35a51d9 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/Size2i.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/Size2i.java
@@ -7,16 +7,13 @@
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
-import javax.annotation.Nonnegative;
public final class Size2i {
- @Nonnegative
public final int width;
- @Nonnegative
public final int height;
@SuppressWarnings("ConstantConditions")
- public Size2i(@Nonnegative int width, @Nonnegative int height) {
+ public Size2i(int width, int height) {
Preconditions.checkArgument(width >= 0, "width must be greater or equal 0");
Preconditions.checkArgument(height >= 0, "height must be greater or equal 0");
this.width = width;
diff --git a/src/main/java/net/neoforged/neoforge/common/util/TransformationHelper.java b/src/main/java/net/neoforged/neoforge/common/util/TransformationHelper.java
index 8aaab10708c..bc95bab652a 100644
--- a/src/main/java/net/neoforged/neoforge/common/util/TransformationHelper.java
+++ b/src/main/java/net/neoforged/neoforge/common/util/TransformationHelper.java
@@ -19,13 +19,13 @@
import java.util.Set;
import net.minecraft.util.Mth;
import net.minecraft.util.StringRepresentable;
-import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Quaternionfc;
import org.joml.Vector3f;
import org.joml.Vector3fc;
import org.joml.Vector4f;
+import org.jspecify.annotations.Nullable;
public final class TransformationHelper {
public static Quaternionf quatFromXYZ(Vector3f xyz, boolean degrees) {
diff --git a/src/main/java/net/neoforged/neoforge/common/world/LevelChunkAuxiliaryLightManager.java b/src/main/java/net/neoforged/neoforge/common/world/LevelChunkAuxiliaryLightManager.java
index 96da10511d7..d13aa360a32 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/LevelChunkAuxiliaryLightManager.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/LevelChunkAuxiliaryLightManager.java
@@ -21,7 +21,7 @@
import net.minecraft.world.level.lighting.LightEngine;
import net.neoforged.neoforge.network.payload.AuxiliaryLightDataPayload;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
public final class LevelChunkAuxiliaryLightManager implements AuxiliaryLightManager {
diff --git a/src/main/java/net/neoforged/neoforge/common/world/MobSpawnSettingsBuilder.java b/src/main/java/net/neoforged/neoforge/common/world/MobSpawnSettingsBuilder.java
index c9cb58f9551..f0fbff3cd13 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/MobSpawnSettingsBuilder.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/MobSpawnSettingsBuilder.java
@@ -11,7 +11,7 @@
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.MobSpawnSettings;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class MobSpawnSettingsBuilder extends MobSpawnSettings.Builder {
private final Set typesView = Collections.unmodifiableSet(this.spawners.keySet());
@@ -35,8 +35,7 @@ public Set> getEntityTypes() {
return this.costView;
}
- @Nullable
- public MobSpawnSettings.MobSpawnCost getCost(EntityType> type) {
+ public MobSpawnSettings.@Nullable MobSpawnCost getCost(EntityType> type) {
return this.mobSpawnCosts.get(type);
}
diff --git a/src/main/java/net/neoforged/neoforge/common/world/ModifiableBiomeInfo.java b/src/main/java/net/neoforged/neoforge/common/world/ModifiableBiomeInfo.java
index 74d844fdbf5..9e257adcbf0 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/ModifiableBiomeInfo.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/ModifiableBiomeInfo.java
@@ -19,7 +19,7 @@
import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.MobSpawnSettings;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/main/java/net/neoforged/neoforge/common/world/ModifiableStructureInfo.java b/src/main/java/net/neoforged/neoforge/common/world/ModifiableStructureInfo.java
index 55371a81f97..0bda6b53e18 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/ModifiableStructureInfo.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/ModifiableStructureInfo.java
@@ -10,7 +10,7 @@
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.Structure.StructureSettings;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Holds lazy-evaluable modified structure info.
diff --git a/src/main/java/net/neoforged/neoforge/common/world/NeoForgeAttributeTypes.java b/src/main/java/net/neoforged/neoforge/common/world/NeoForgeAttributeTypes.java
new file mode 100644
index 00000000000..37f41dd2550
--- /dev/null
+++ b/src/main/java/net/neoforged/neoforge/common/world/NeoForgeAttributeTypes.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.common.world;
+
+import net.minecraft.resources.Identifier;
+import net.minecraft.world.attribute.AttributeType;
+import net.minecraft.world.attribute.EnvironmentAttribute;
+
+public final class NeoForgeAttributeTypes {
+ /**
+ * Allows {@link Identifier} to be used as the type of {@link EnvironmentAttribute}.
+ */
+ public static final AttributeType IDENTIFIER = AttributeType.ofNotInterpolated(Identifier.CODEC);
+
+ private NeoForgeAttributeTypes() {}
+}
diff --git a/src/main/java/net/neoforged/neoforge/common/world/NeoForgeEnvironmentAttributes.java b/src/main/java/net/neoforged/neoforge/common/world/NeoForgeEnvironmentAttributes.java
new file mode 100644
index 00000000000..6fcb19528c2
--- /dev/null
+++ b/src/main/java/net/neoforged/neoforge/common/world/NeoForgeEnvironmentAttributes.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) NeoForged and contributors
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+package net.neoforged.neoforge.common.world;
+
+import net.minecraft.resources.Identifier;
+import net.minecraft.world.attribute.EnvironmentAttribute;
+
+/**
+ * NeoForge specific {@link net.minecraft.world.attribute.EnvironmentAttributes}.
+ *
+ * These will be filtered out when syncing to vanilla clients.
+ */
+public final class NeoForgeEnvironmentAttributes {
+ public static Identifier DEFAULT_CUSTOM_CLOUDS = Identifier.withDefaultNamespace("default");
+ public static EnvironmentAttribute CUSTOM_CLOUDS = EnvironmentAttribute.builder(NeoForgeAttributeTypes.IDENTIFIER)
+ .defaultValue(DEFAULT_CUSTOM_CLOUDS)
+ .syncable()
+ .build();
+ public static Identifier DEFAULT_CUSTOM_SKYBOX = Identifier.withDefaultNamespace("default");
+ public static EnvironmentAttribute CUSTOM_SKYBOX = EnvironmentAttribute.builder(NeoForgeAttributeTypes.IDENTIFIER)
+ .defaultValue(DEFAULT_CUSTOM_SKYBOX)
+ .syncable()
+ .build();
+ public static Identifier DEFAULT_CUSTOM_WEATHER_EFFECTS = Identifier.withDefaultNamespace("default");
+ public static EnvironmentAttribute CUSTOM_WEATHER_EFFECTS = EnvironmentAttribute.builder(NeoForgeAttributeTypes.IDENTIFIER)
+ .defaultValue(DEFAULT_CUSTOM_WEATHER_EFFECTS)
+ .syncable()
+ .build();
+
+ private NeoForgeEnvironmentAttributes() {}
+}
diff --git a/src/main/java/net/neoforged/neoforge/common/world/StructureSettingsBuilder.java b/src/main/java/net/neoforged/neoforge/common/world/StructureSettingsBuilder.java
index e131e0e9a69..9e61412804e 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/StructureSettingsBuilder.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/StructureSettingsBuilder.java
@@ -20,7 +20,7 @@
import net.minecraft.world.level.levelgen.structure.Structure.StructureSettings;
import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride;
import net.minecraft.world.level.levelgen.structure.TerrainAdjustment;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class StructureSettingsBuilder {
private HolderSet biomes;
diff --git a/src/main/java/net/neoforged/neoforge/common/world/chunk/ForcedChunkManager.java b/src/main/java/net/neoforged/neoforge/common/world/chunk/ForcedChunkManager.java
index c9b12b0cf1e..3d9f19c3b3a 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/chunk/ForcedChunkManager.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/chunk/ForcedChunkManager.java
@@ -24,7 +24,6 @@
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
-import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.UUIDUtil;
@@ -40,9 +39,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
-@ParametersAreNonnullByDefault
public class ForcedChunkManager {
private static final Logger LOGGER = LogManager.getLogger();
diff --git a/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketController.java b/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketController.java
index f69a0c0ab07..c5d6db9185b 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketController.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketController.java
@@ -7,13 +7,12 @@
import java.util.Objects;
import java.util.UUID;
-import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.TicketStorage;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A class used to manage chunk loading tickets associated with a specific ID.
@@ -25,7 +24,6 @@
* @param callback a callback to be called when the tickets are loaded, in order to validate whether they're still active or not. {@code null} should be used when a
* callback needn't be provided
*/
-@ParametersAreNonnullByDefault
public record TicketController(Identifier id, @Nullable LoadingValidationCallback callback) {
public TicketController {
Objects.requireNonNull(id, "id must not be null");
diff --git a/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketHelper.java b/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketHelper.java
index ddcce4ae9db..3178f216555 100644
--- a/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketHelper.java
+++ b/src/main/java/net/neoforged/neoforge/common/world/chunk/TicketHelper.java
@@ -10,7 +10,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.TicketStorage;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Class to help mods remove no longer valid tickets before they are activated on load.
diff --git a/src/main/java/net/neoforged/neoforge/data/event/GatherDataEvent.java b/src/main/java/net/neoforged/neoforge/data/event/GatherDataEvent.java
index c4b34eff0cd..817b09229e5 100644
--- a/src/main/java/net/neoforged/neoforge/data/event/GatherDataEvent.java
+++ b/src/main/java/net/neoforged/neoforge/data/event/GatherDataEvent.java
@@ -51,7 +51,7 @@
import net.neoforged.neoforge.resource.ResourcePackLoader;
import org.apache.commons.lang3.function.Consumers;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public abstract class GatherDataEvent extends Event implements IModBusEvent {
private final DataGenerator dataGenerator;
diff --git a/src/main/java/net/neoforged/neoforge/entity/XpOrbTargetingEvent.java b/src/main/java/net/neoforged/neoforge/entity/XpOrbTargetingEvent.java
index 86e8fc01461..9f53e172c09 100644
--- a/src/main/java/net/neoforged/neoforge/entity/XpOrbTargetingEvent.java
+++ b/src/main/java/net/neoforged/neoforge/entity/XpOrbTargetingEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.player.PlayerXpEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Event to determine which player an XP Orb should follow.
diff --git a/src/main/java/net/neoforged/neoforge/event/AnvilUpdateEvent.java b/src/main/java/net/neoforged/neoforge/event/AnvilUpdateEvent.java
index dd81df93bf5..db5116fd914 100644
--- a/src/main/java/net/neoforged/neoforge/event/AnvilUpdateEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/AnvilUpdateEvent.java
@@ -9,7 +9,7 @@
import net.minecraft.world.item.ItemStack;
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired when an anvil's left input is not empty, and any of the inputs (left, right, or name) are changed.
diff --git a/src/main/java/net/neoforged/neoforge/event/BlockEntityTypeAddBlocksEvent.java b/src/main/java/net/neoforged/neoforge/event/BlockEntityTypeAddBlocksEvent.java
index a2ec18b8c60..7d801870054 100644
--- a/src/main/java/net/neoforged/neoforge/event/BlockEntityTypeAddBlocksEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/BlockEntityTypeAddBlocksEvent.java
@@ -21,7 +21,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.neoforge.mixins.BlockEntityTypeAccessor;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Allows injecting new blocks into a block entity's {@link BlockEntityType#validBlocks} field in a safe manner.
diff --git a/src/main/java/net/neoforged/neoforge/event/CommandEvent.java b/src/main/java/net/neoforged/neoforge/event/CommandEvent.java
index 97e58edce1a..c1374293b77 100644
--- a/src/main/java/net/neoforged/neoforge/event/CommandEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/CommandEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* CommandEvent is fired after a command is parsed, but before it is executed.
diff --git a/src/main/java/net/neoforged/neoforge/event/EventHooks.java b/src/main/java/net/neoforged/neoforge/event/EventHooks.java
index ac81a6e959b..191d4002061 100644
--- a/src/main/java/net/neoforged/neoforge/event/EventHooks.java
+++ b/src/main/java/net/neoforged/neoforge/event/EventHooks.java
@@ -179,7 +179,7 @@
import net.neoforged.neoforge.event.tick.ServerTickEvent;
import net.neoforged.neoforge.resource.ReloadListenerSort;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class EventHooks {
public static boolean onMultiBlockPlace(@Nullable Entity entity, List blockSnapshots, Direction direction) {
@@ -572,7 +572,7 @@ public static void onPlayerFall(Player player, float distance, float multiplier)
NeoForge.EVENT_BUS.post(new PlayerFlyableFallEvent(player, distance, multiplier));
}
- public static boolean onPlayerSpawnSet(Player player, @Nullable ServerPlayer.RespawnConfig respawnConfig) {
+ public static boolean onPlayerSpawnSet(Player player, ServerPlayer.@Nullable RespawnConfig respawnConfig) {
return NeoForge.EVENT_BUS.post(new PlayerSetSpawnEvent(player, respawnConfig)).isCanceled();
}
diff --git a/src/main/java/net/neoforged/neoforge/event/GatherSkippedAttributeTooltipsEvent.java b/src/main/java/net/neoforged/neoforge/event/GatherSkippedAttributeTooltipsEvent.java
index bdc658a8e02..bb8a1d27bc8 100644
--- a/src/main/java/net/neoforged/neoforge/event/GatherSkippedAttributeTooltipsEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/GatherSkippedAttributeTooltipsEvent.java
@@ -13,7 +13,7 @@
import net.minecraft.world.item.ItemStack;
import net.neoforged.bus.api.Event;
import net.neoforged.neoforge.common.util.AttributeTooltipContext;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is used to collect the IDs of attribute modifiers that will not be displayed in item tooltips.
diff --git a/src/main/java/net/neoforged/neoforge/event/ItemAttributeModifierEvent.java b/src/main/java/net/neoforged/neoforge/event/ItemAttributeModifierEvent.java
index a1234ccc49a..81e83e583d7 100644
--- a/src/main/java/net/neoforged/neoforge/event/ItemAttributeModifierEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/ItemAttributeModifierEvent.java
@@ -22,7 +22,7 @@
import net.minecraft.world.item.component.ItemAttributeModifiers;
import net.neoforged.bus.api.Event;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired when the attributes for an item stack are queried (for any reason) through {@link ItemStack#getAttributeModifiers()}.
@@ -211,8 +211,7 @@ boolean removeModifier(Holder attribute, Identifier id) {
*
* @return the previous modifier, or null if there was no previous modifier with the same id
*/
- @Nullable
- ItemAttributeModifiers.Entry replaceModifier(Holder attribute, AttributeModifier modifier, EquipmentSlotGroup slot) {
+ ItemAttributeModifiers.@Nullable Entry replaceModifier(Holder attribute, AttributeModifier modifier, EquipmentSlotGroup slot) {
Key key = new Key(attribute, modifier.id());
ItemAttributeModifiers.Entry entry = new ItemAttributeModifiers.Entry(attribute, modifier, slot);
if (entriesByKey.containsKey(key)) {
diff --git a/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java b/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java
index 0d056f7bf5d..5537ec518a3 100644
--- a/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java
@@ -16,7 +16,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when a {@link LootTable} is loaded from JSON.
diff --git a/src/main/java/net/neoforged/neoforge/event/ModMismatchEvent.java b/src/main/java/net/neoforged/neoforge/event/ModMismatchEvent.java
index 049d7d6632a..b5275f969b1 100644
--- a/src/main/java/net/neoforged/neoforge/event/ModMismatchEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/ModMismatchEvent.java
@@ -21,7 +21,7 @@
import net.neoforged.neoforgespi.language.IModInfo;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fires when the mod loader is in the process of loading a world that was last saved
diff --git a/src/main/java/net/neoforged/neoforge/event/OnDatapackSyncEvent.java b/src/main/java/net/neoforged/neoforge/event/OnDatapackSyncEvent.java
index b458e08f4b4..fcf66c30831 100644
--- a/src/main/java/net/neoforged/neoforge/event/OnDatapackSyncEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/OnDatapackSyncEvent.java
@@ -14,7 +14,7 @@
import net.minecraft.server.players.PlayerList;
import net.minecraft.world.item.crafting.RecipeType;
import net.neoforged.bus.api.Event;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fires when a player joins the server or when the reload command is ran,
diff --git a/src/main/java/net/neoforged/neoforge/event/PlayLevelSoundEvent.java b/src/main/java/net/neoforged/neoforge/event/PlayLevelSoundEvent.java
index 37024ec7a3d..fb8d608d5a1 100644
--- a/src/main/java/net/neoforged/neoforge/event/PlayLevelSoundEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/PlayLevelSoundEvent.java
@@ -15,7 +15,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* PlayLevelSoundEvent is fired when a sound is played on a {@link Level}.
diff --git a/src/main/java/net/neoforged/neoforge/event/VanillaGameEvent.java b/src/main/java/net/neoforged/neoforge/event/VanillaGameEvent.java
index b36c2513b2b..8a69b8181b7 100644
--- a/src/main/java/net/neoforged/neoforge/event/VanillaGameEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/VanillaGameEvent.java
@@ -13,7 +13,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* VanillaGameEvent is fired on the server whenever one of Vanilla's {@link GameEvent GameEvents} fire.
diff --git a/src/main/java/net/neoforged/neoforge/event/enchanting/GetEnchantmentLevelEvent.java b/src/main/java/net/neoforged/neoforge/event/enchanting/GetEnchantmentLevelEvent.java
index f902fce284f..15994cb27f7 100644
--- a/src/main/java/net/neoforged/neoforge/event/enchanting/GetEnchantmentLevelEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/enchanting/GetEnchantmentLevelEvent.java
@@ -14,7 +14,7 @@
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.neoforged.bus.api.Event;
import net.neoforged.neoforge.common.extensions.IItemStackExtension;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired whenever the enchantment level of a particular item is requested for gameplay purposes.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/EntityTeleportEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/EntityTeleportEvent.java
index 4f26839a9a3..bfacb3f580f 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/EntityTeleportEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/EntityTeleportEvent.java
@@ -17,7 +17,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* EntityTeleportEvent is fired when an event involving any teleportation of an Entity occurs.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/RegisterSpawnPlacementsEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/RegisterSpawnPlacementsEvent.java
index e8ddc465a86..665f44b1125 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/RegisterSpawnPlacementsEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/RegisterSpawnPlacementsEvent.java
@@ -19,7 +19,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.event.IModBusEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event allows each {@link EntityType} to have a {@link SpawnPlacements.SpawnPredicate} registered or modified.
@@ -67,7 +67,7 @@ public void register(EntityType entityType, SpawnPlacement
* Use {@code null} for the placement or heightmap to leave them as is (which should be done in almost every case)
*/
@SuppressWarnings("unchecked")
- public void register(EntityType entityType, @Nullable SpawnPlacementType placementType, @Nullable Heightmap.Types heightmap, SpawnPlacements.SpawnPredicate predicate, Operation operation) {
+ public void register(EntityType entityType, @Nullable SpawnPlacementType placementType, Heightmap.@Nullable Types heightmap, SpawnPlacements.SpawnPredicate predicate, Operation operation) {
if (!map.containsKey(entityType)) {
if (placementType == null) {
throw new NullPointerException("Registering a new Spawn Predicate requires a nonnull placement type! Entity Type: " + BuiltInRegistries.ENTITY_TYPE.getKey(entityType));
@@ -103,8 +103,7 @@ public static class MergedSpawnPredicate {
private final SpawnPlacements.SpawnPredicate originalPredicate;
private final List> orPredicates;
private final List> andPredicates;
- @Nullable
- private SpawnPlacements.SpawnPredicate replacementPredicate;
+ private SpawnPlacements.@Nullable SpawnPredicate replacementPredicate;
private SpawnPlacementType spawnType;
private Heightmap.Types heightmapType;
@@ -125,7 +124,7 @@ public Heightmap.Types getHeightmapType() {
return heightmapType;
}
- private void merge(Operation operation, SpawnPlacements.SpawnPredicate predicate, @Nullable SpawnPlacementType spawnType, @Nullable Heightmap.Types heightmapType) {
+ private void merge(Operation operation, SpawnPlacements.SpawnPredicate predicate, @Nullable SpawnPlacementType spawnType, Heightmap.@Nullable Types heightmapType) {
if (operation == Operation.AND) {
andPredicates.add(predicate);
} else if (operation == Operation.OR) {
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/BabyEntitySpawnEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/BabyEntitySpawnEvent.java
index 956a699c93c..54f2df0e032 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/BabyEntitySpawnEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/BabyEntitySpawnEvent.java
@@ -13,7 +13,7 @@
import net.minecraft.world.entity.player.Player;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* BabyEntitySpawnEvent is fired just before a baby entity is about to be spawned.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/EffectParticleModificationEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/EffectParticleModificationEvent.java
index cb612cb2fca..f174c6b325d 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/EffectParticleModificationEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/EffectParticleModificationEvent.java
@@ -11,7 +11,7 @@
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fires for each effect to allow modification or replacement of the particle options (you can set it to null to reset it to default).
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/FinalizeSpawnEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/FinalizeSpawnEvent.java
index 66722912292..23562ebc11c 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/FinalizeSpawnEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/FinalizeSpawnEvent.java
@@ -22,7 +22,7 @@
import net.neoforged.neoforge.common.NeoForgeEventHandler;
import net.neoforged.neoforge.event.EventHooks;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired before {@link Mob#finalizeSpawn} is called.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingChangeTargetEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingChangeTargetEvent.java
index e8cde2014c8..411e97c1933 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingChangeTargetEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingChangeTargetEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event allows you to change the target an entity has.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingEvent.java
index febd2cd3161..5f52ef9a388 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingEvent.java
@@ -12,7 +12,7 @@
import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.EntityEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* LivingEvent is fired whenever an event involving a {@link LivingEntity} occurs.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingExperienceDropEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingExperienceDropEvent.java
index 28e9212cab3..18da73402ea 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/LivingExperienceDropEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/LivingExperienceDropEvent.java
@@ -8,7 +8,7 @@
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Event for when an entity drops experience on its death, can be used to change
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/MobEffectEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/MobEffectEvent.java
index c1172627092..fbd4eaf6627 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/MobEffectEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/MobEffectEvent.java
@@ -13,7 +13,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired when an interaction between a {@link LivingEntity} and {@link MobEffectInstance} happens.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/living/MobSpawnEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/living/MobSpawnEvent.java
index 4c70e9de234..1020e2c2b8a 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/living/MobSpawnEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/living/MobSpawnEvent.java
@@ -23,7 +23,7 @@
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.entity.RegisterSpawnPlacementsEvent;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This class holds all events relating to the entire flow of mob spawns.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/BonemealEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/BonemealEvent.java
index 33f93e61ca3..35bfe6ffad7 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/BonemealEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/BonemealEvent.java
@@ -13,7 +13,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is called when a player attempts to use bone meal on a block.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/CanContinueSleepingEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/CanContinueSleepingEvent.java
index dbf313c4a60..ca4fa675002 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/CanContinueSleepingEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/CanContinueSleepingEvent.java
@@ -10,7 +10,7 @@
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player.BedSleepingProblem;
import net.neoforged.neoforge.event.entity.living.LivingEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired when the game checks if a sleeping entity may continue sleeping.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/CanPlayerSleepEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/CanPlayerSleepEvent.java
index fa1e1581246..72c056d2f90 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/CanPlayerSleepEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/CanPlayerSleepEvent.java
@@ -10,7 +10,7 @@
import net.minecraft.world.entity.player.Player.BedSleepingProblem;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Called from {@link ServerPlayer#startSleepInBed(BlockPos)} when a player attempts to sleep.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/ItemFishedEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/ItemFishedEvent.java
index b81bac728fe..fd1e3b289cf 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/ItemFishedEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/ItemFishedEvent.java
@@ -7,7 +7,6 @@
import com.google.common.base.Preconditions;
import java.util.List;
-import javax.annotation.Nonnegative;
import net.minecraft.core.NonNullList;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.item.ItemStack;
@@ -47,7 +46,7 @@ public int getRodDamage() {
*
* @param rodDamage The damage the rod will take. Must be nonnegative
*/
- public void damageRodBy(@Nonnegative int rodDamage) {
+ public void damageRodBy(int rodDamage) {
Preconditions.checkArgument(rodDamage >= 0);
this.rodDamage = rodDamage;
}
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/ItemTooltipEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/ItemTooltipEvent.java
index d875d68996f..c22cf4f79c2 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/ItemTooltipEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/ItemTooltipEvent.java
@@ -11,7 +11,7 @@
import net.minecraft.world.item.Item.TooltipContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class ItemTooltipEvent extends PlayerEvent {
private final TooltipFlag flags;
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerDestroyItemEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerDestroyItemEvent.java
index 90d51d4aae5..679b424195a 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerDestroyItemEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerDestroyItemEvent.java
@@ -17,7 +17,7 @@
import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.EventHooks;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* PlayerDestroyItemEvent is fired when a player destroys an item.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java
index 66c55569e4a..4b64505d302 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java
@@ -24,7 +24,7 @@
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.event.entity.living.LivingEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* PlayerEvent is fired whenever an event involving a {@link Player} occurs.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerInteractEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerInteractEvent.java
index b317103a29b..cdf8a07d07e 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerInteractEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerInteractEvent.java
@@ -28,7 +28,7 @@
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* PlayerInteractEvent is fired when a player interacts in some way.
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerSetSpawnEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerSetSpawnEvent.java
index 6110513be6a..252987fd9f8 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerSetSpawnEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerSetSpawnEvent.java
@@ -11,7 +11,7 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired when a player's spawn point is set or reset.
@@ -23,7 +23,7 @@ public class PlayerSetSpawnEvent extends PlayerEvent implements ICancellableEven
@Nullable
private final BlockPos newSpawn;
- public PlayerSetSpawnEvent(Player player, @Nullable ServerPlayer.RespawnConfig respawnConfig) {
+ public PlayerSetSpawnEvent(Player player, ServerPlayer.@Nullable RespawnConfig respawnConfig) {
super(player);
this.spawnLevel = ServerPlayer.RespawnConfig.getDimensionOrDefault(respawnConfig);
this.newSpawn = respawnConfig != null ? respawnConfig.respawnData().pos() : null;
diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/UseItemOnBlockEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/UseItemOnBlockEvent.java
index 99c6172c16b..631299db9b0 100644
--- a/src/main/java/net/neoforged/neoforge/event/entity/player/UseItemOnBlockEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/entity/player/UseItemOnBlockEvent.java
@@ -22,7 +22,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.extensions.IItemExtension;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fires on both the client and server thread when a player interacts with a block.
diff --git a/src/main/java/net/neoforged/neoforge/event/furnace/FurnaceFuelBurnTimeEvent.java b/src/main/java/net/neoforged/neoforge/event/furnace/FurnaceFuelBurnTimeEvent.java
index 1f82354ed05..221c37c7e88 100644
--- a/src/main/java/net/neoforged/neoforge/event/furnace/FurnaceFuelBurnTimeEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/furnace/FurnaceFuelBurnTimeEvent.java
@@ -13,7 +13,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.EventHooks;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* {@link FurnaceFuelBurnTimeEvent} is fired when determining the fuel value for an ItemStack.
diff --git a/src/main/java/net/neoforged/neoforge/event/level/BlockDropsEvent.java b/src/main/java/net/neoforged/neoforge/event/level/BlockDropsEvent.java
index 609f65f471b..e6d9cac03b4 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/BlockDropsEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/BlockDropsEvent.java
@@ -18,7 +18,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.neoforge.common.loot.LootModifier;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fired when a block is broken and the drops have been determined, but before they have been added to the world. This event can be used to manipulate the dropped items and experience.
diff --git a/src/main/java/net/neoforged/neoforge/event/level/BlockEvent.java b/src/main/java/net/neoforged/neoforge/event/level/BlockEvent.java
index 4fc517f429d..03309542d08 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/BlockEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/BlockEvent.java
@@ -26,7 +26,7 @@
import net.neoforged.neoforge.common.ItemAbilities;
import net.neoforged.neoforge.common.ItemAbility;
import net.neoforged.neoforge.common.util.BlockSnapshot;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public abstract class BlockEvent extends Event {
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("neoforge.debugBlockEvent", "false"));
diff --git a/src/main/java/net/neoforged/neoforge/event/level/BlockGrowFeatureEvent.java b/src/main/java/net/neoforged/neoforge/event/level/BlockGrowFeatureEvent.java
index ee002c72141..b77518517c2 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/BlockGrowFeatureEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/BlockGrowFeatureEvent.java
@@ -13,7 +13,7 @@
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired whenever a block (like a sapling) grows into a feature (like a tree).
diff --git a/src/main/java/net/neoforged/neoforge/event/level/ChunkTicketLevelUpdatedEvent.java b/src/main/java/net/neoforged/neoforge/event/level/ChunkTicketLevelUpdatedEvent.java
index ceb9d7fbb48..b6bfb895b60 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/ChunkTicketLevelUpdatedEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/ChunkTicketLevelUpdatedEvent.java
@@ -10,7 +10,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired whenever a chunk has its ticket level changed via the server's ChunkMap.
diff --git a/src/main/java/net/neoforged/neoforge/event/level/LevelEvent.java b/src/main/java/net/neoforged/neoforge/event/level/LevelEvent.java
index 1c1108e93b4..d6fef659636 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/LevelEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/LevelEvent.java
@@ -20,7 +20,7 @@
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This event is fired whenever an event involving a {@link LevelAccessor} occurs.
@@ -130,8 +130,7 @@ public ServerLevelData getSettings() {
public static class PotentialSpawns extends LevelEvent implements ICancellableEvent {
private final MobCategory mobcategory;
private final BlockPos pos;
- @Nullable
- private WeightedList.Builder list;
+ private WeightedList.@Nullable Builder list;
private List> view;
public PotentialSpawns(LevelAccessor level, MobCategory category, BlockPos pos, WeightedList oldList) {
diff --git a/src/main/java/net/neoforged/neoforge/event/level/PistonEvent.java b/src/main/java/net/neoforged/neoforge/event/level/PistonEvent.java
index a3443048864..befab3e7164 100644
--- a/src/main/java/net/neoforged/neoforge/event/level/PistonEvent.java
+++ b/src/main/java/net/neoforged/neoforge/event/level/PistonEvent.java
@@ -10,7 +10,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.piston.PistonStructureResolver;
import net.neoforged.bus.api.ICancellableEvent;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Base piston event, use {@link PistonEvent.Post} and {@link PistonEvent.Pre}
diff --git a/src/main/java/net/neoforged/neoforge/fluids/BaseFlowingFluid.java b/src/main/java/net/neoforged/neoforge/fluids/BaseFlowingFluid.java
index f956bbec9e5..2e2b6289cfc 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/BaseFlowingFluid.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/BaseFlowingFluid.java
@@ -26,7 +26,7 @@
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.neoforged.neoforge.common.SoundActions;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Base implementation of a {@link FlowingFluid} for mods to use.
diff --git a/src/main/java/net/neoforged/neoforge/fluids/CauldronFluidContent.java b/src/main/java/net/neoforged/neoforge/fluids/CauldronFluidContent.java
index c386dc984e4..9a08e499a43 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/CauldronFluidContent.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/CauldronFluidContent.java
@@ -20,7 +20,7 @@
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.transfer.fluid.CauldronWrapper;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Fluid content information for cauldrons.
diff --git a/src/main/java/net/neoforged/neoforge/fluids/FluidStack.java b/src/main/java/net/neoforged/neoforge/fluids/FluidStack.java
index f4f9e4454d9..0e1e4452f53 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/FluidStack.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/FluidStack.java
@@ -34,7 +34,7 @@
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.neoforge.common.MutableDataComponentHolder;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/main/java/net/neoforged/neoforge/fluids/FluidStackLinkedSet.java b/src/main/java/net/neoforged/neoforge/fluids/FluidStackLinkedSet.java
index e2f584b5658..cc20f303a5a 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/FluidStackLinkedSet.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/FluidStackLinkedSet.java
@@ -8,7 +8,7 @@
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenCustomHashSet;
import java.util.Set;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Utility class for creating {@linkplain ObjectLinkedOpenCustomHashSet linked set} for {@link FluidStack}
diff --git a/src/main/java/net/neoforged/neoforge/fluids/FluidType.java b/src/main/java/net/neoforged/neoforge/fluids/FluidType.java
index ae34ba4a193..4eac8bc4159 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/FluidType.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/FluidType.java
@@ -46,7 +46,7 @@
import net.neoforged.neoforge.common.SoundActions;
import net.neoforged.neoforge.common.util.Lazy;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A definition of common attributes, properties, and methods that is applied
diff --git a/src/main/java/net/neoforged/neoforge/fluids/FluidUtil.java b/src/main/java/net/neoforged/neoforge/fluids/FluidUtil.java
index 6efdf8152ba..14e60a848b6 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/FluidUtil.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/FluidUtil.java
@@ -42,7 +42,7 @@
import net.neoforged.neoforge.transfer.access.ItemAccess;
import net.neoforged.neoforge.transfer.fluid.FluidResource;
import net.neoforged.neoforge.transfer.item.VanillaContainerWrapper;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* @deprecated Use {@link ResourceHandler} with a {@link FluidResource} instead of {@link IFluidHandler}.
diff --git a/src/main/java/net/neoforged/neoforge/fluids/RegisterCauldronFluidContentEvent.java b/src/main/java/net/neoforged/neoforge/fluids/RegisterCauldronFluidContentEvent.java
index 57c5bb38456..6c86244e651 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/RegisterCauldronFluidContentEvent.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/RegisterCauldronFluidContentEvent.java
@@ -17,7 +17,7 @@
import net.neoforged.bus.api.Event;
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.neoforge.capabilities.Capabilities;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Event to register {@link CauldronFluidContent} for modded cauldrons.
diff --git a/src/main/java/net/neoforged/neoforge/fluids/crafting/FluidIngredient.java b/src/main/java/net/neoforged/neoforge/fluids/crafting/FluidIngredient.java
index c76edc65d90..50977a42532 100644
--- a/src/main/java/net/neoforged/neoforge/fluids/crafting/FluidIngredient.java
+++ b/src/main/java/net/neoforged/neoforge/fluids/crafting/FluidIngredient.java
@@ -24,7 +24,7 @@
import net.neoforged.neoforge.fluids.crafting.display.FluidSlotDisplay;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* This class serves as the fluid analogue of an item {@link Ingredient},
diff --git a/src/main/java/net/neoforged/neoforge/internal/BrandingControl.java b/src/main/java/net/neoforged/neoforge/internal/BrandingControl.java
index a705c018c14..cdd0ab67dc0 100644
--- a/src/main/java/net/neoforged/neoforge/internal/BrandingControl.java
+++ b/src/main/java/net/neoforged/neoforge/internal/BrandingControl.java
@@ -16,7 +16,7 @@
import net.neoforged.fml.ModList;
import net.neoforged.fml.i18n.FMLTranslations;
import net.neoforged.neoforge.common.NeoForgeVersion;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class BrandingControl {
public static final String BRANDING_NAME = "NeoForge";
diff --git a/src/main/java/net/neoforged/neoforge/internal/NeoForgeProxy.java b/src/main/java/net/neoforged/neoforge/internal/NeoForgeProxy.java
index f7c6993baa4..f909bfbb937 100644
--- a/src/main/java/net/neoforged/neoforge/internal/NeoForgeProxy.java
+++ b/src/main/java/net/neoforged/neoforge/internal/NeoForgeProxy.java
@@ -14,7 +14,7 @@
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Allows common code to call client-only methods, through {@code NeoForgeClientProxy}.
@@ -47,8 +47,7 @@ public TooltipFlag getTooltipFlag() {
return TooltipFlag.NORMAL;
}
- @Nullable
- public HolderLookup.RegistryLookup resolveLookup(ResourceKey extends Registry> key) {
+ public HolderLookup.@Nullable RegistryLookup resolveLookup(ResourceKey extends Registry> key) {
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if (server != null) {
return server.registryAccess().lookup(key).orElse(null);
diff --git a/src/main/java/net/neoforged/neoforge/internal/NeoForgeVersionCheck.java b/src/main/java/net/neoforged/neoforge/internal/NeoForgeVersionCheck.java
index 3de884b2139..1e647a437e4 100644
--- a/src/main/java/net/neoforged/neoforge/internal/NeoForgeVersionCheck.java
+++ b/src/main/java/net/neoforged/neoforge/internal/NeoForgeVersionCheck.java
@@ -8,7 +8,7 @@
import net.neoforged.fml.ModList;
import net.neoforged.fml.VersionChecker;
import net.neoforged.neoforge.common.NeoForgeMod;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
public class NeoForgeVersionCheck {
public static VersionChecker.Status getStatus() {
diff --git a/src/main/java/net/neoforged/neoforge/items/ItemHandlerHelper.java b/src/main/java/net/neoforged/neoforge/items/ItemHandlerHelper.java
index 509b781c11e..b36b8d6c161 100644
--- a/src/main/java/net/neoforged/neoforge/items/ItemHandlerHelper.java
+++ b/src/main/java/net/neoforged/neoforge/items/ItemHandlerHelper.java
@@ -20,7 +20,7 @@
import net.neoforged.neoforge.transfer.item.ItemUtil;
import net.neoforged.neoforge.transfer.resource.Resource;
import net.neoforged.neoforge.transfer.transaction.TransactionContext;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* @deprecated Use {@link ResourceHandler} with an {@link ItemResource} instead of {@link IItemHandler}.
diff --git a/src/main/java/net/neoforged/neoforge/items/wrapper/SidedInvWrapper.java b/src/main/java/net/neoforged/neoforge/items/wrapper/SidedInvWrapper.java
index 698d69a2c72..e9fa2c4e6ef 100644
--- a/src/main/java/net/neoforged/neoforge/items/wrapper/SidedInvWrapper.java
+++ b/src/main/java/net/neoforged/neoforge/items/wrapper/SidedInvWrapper.java
@@ -14,7 +14,7 @@
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
import net.neoforged.neoforge.transfer.item.WorldlyContainerWrapper;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* @deprecated Use {@link WorldlyContainerWrapper} instead.
diff --git a/src/main/java/net/neoforged/neoforge/model/data/ModelData.java b/src/main/java/net/neoforged/neoforge/model/data/ModelData.java
index 7a2b0778d22..a394b1bc285 100644
--- a/src/main/java/net/neoforged/neoforge/model/data/ModelData.java
+++ b/src/main/java/net/neoforged/neoforge/model/data/ModelData.java
@@ -15,7 +15,7 @@
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A container for data to be passed to {@code BlockStateModel} instances.
diff --git a/src/main/java/net/neoforged/neoforge/network/DualStackUtils.java b/src/main/java/net/neoforged/neoforge/network/DualStackUtils.java
index 15fc6805d0c..22fccf640f1 100644
--- a/src/main/java/net/neoforged/neoforge/network/DualStackUtils.java
+++ b/src/main/java/net/neoforged/neoforge/network/DualStackUtils.java
@@ -16,7 +16,7 @@
import net.minecraft.util.HttpUtil;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class DualStackUtils {
diff --git a/src/main/java/net/neoforged/neoforge/network/PacketDistributor.java b/src/main/java/net/neoforged/neoforge/network/PacketDistributor.java
index 642e8985d4f..c4df8d0f287 100644
--- a/src/main/java/net/neoforged/neoforge/network/PacketDistributor.java
+++ b/src/main/java/net/neoforged/neoforge/network/PacketDistributor.java
@@ -20,7 +20,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Means to distribute packets in various ways.
diff --git a/src/main/java/net/neoforged/neoforge/network/filters/CommandTreeCleaner.java b/src/main/java/net/neoforged/neoforge/network/filters/CommandTreeCleaner.java
index 5634727989e..3cf801ab0ce 100644
--- a/src/main/java/net/neoforged/neoforge/network/filters/CommandTreeCleaner.java
+++ b/src/main/java/net/neoforged/neoforge/network/filters/CommandTreeCleaner.java
@@ -21,7 +21,7 @@
import net.minecraft.resources.Identifier;
import net.minecraft.server.permissions.PermissionCheck;
import net.minecraft.server.permissions.PermissionProviderCheck;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
// TODO 1.21.6: Investigate whether the NodeBuilder/NodeInspector are actually correctly implemented and whether the filtering can be done directly in the NodeBuilder
class CommandTreeCleaner {
diff --git a/src/main/java/net/neoforged/neoforge/network/negotiation/NetworkComponentNegotiator.java b/src/main/java/net/neoforged/neoforge/network/negotiation/NetworkComponentNegotiator.java
index 00f303b4dc4..986d6ad5d3b 100644
--- a/src/main/java/net/neoforged/neoforge/network/negotiation/NetworkComponentNegotiator.java
+++ b/src/main/java/net/neoforged/neoforge/network/negotiation/NetworkComponentNegotiator.java
@@ -16,8 +16,8 @@
import net.minecraft.resources.Identifier;
import net.neoforged.fml.ModList;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;
+import org.jspecify.annotations.Nullable;
/**
* Negotiates the network components between the server and client.
diff --git a/src/main/java/net/neoforged/neoforge/network/payload/CommonRegisterPayload.java b/src/main/java/net/neoforged/neoforge/network/payload/CommonRegisterPayload.java
index 6081ea70631..0cace6fec48 100644
--- a/src/main/java/net/neoforged/neoforge/network/payload/CommonRegisterPayload.java
+++ b/src/main/java/net/neoforged/neoforge/network/payload/CommonRegisterPayload.java
@@ -14,7 +14,7 @@
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.Identifier;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Common Register, used to send play-phase channels during the configuration phase.
diff --git a/src/main/java/net/neoforged/neoforge/network/registration/ChannelAttributes.java b/src/main/java/net/neoforged/neoforge/network/registration/ChannelAttributes.java
index c746f162d79..9b0c7e533b5 100644
--- a/src/main/java/net/neoforged/neoforge/network/registration/ChannelAttributes.java
+++ b/src/main/java/net/neoforged/neoforge/network/registration/ChannelAttributes.java
@@ -20,7 +20,7 @@
import net.neoforged.neoforge.network.payload.ModdedNetworkPayload;
import net.neoforged.neoforge.network.payload.ModdedNetworkQueryPayload;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Utilities for manipulation of Netty {@link Channel} attributes
diff --git a/src/main/java/net/neoforged/neoforge/network/registration/NetworkPayloadSetup.java b/src/main/java/net/neoforged/neoforge/network/registration/NetworkPayloadSetup.java
index 1bc41a14165..f668e967bdb 100644
--- a/src/main/java/net/neoforged/neoforge/network/registration/NetworkPayloadSetup.java
+++ b/src/main/java/net/neoforged/neoforge/network/registration/NetworkPayloadSetup.java
@@ -17,7 +17,7 @@
import net.minecraft.resources.Identifier;
import net.neoforged.neoforge.network.negotiation.NegotiationResult;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Represents a complete negotiated network, which is stored on the client and server.
diff --git a/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java b/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java
index f40596e36a0..93fdbb84a6b 100644
--- a/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java
+++ b/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java
@@ -64,8 +64,8 @@
import net.neoforged.neoforge.network.payload.ModdedNetworkQueryPayload;
import net.neoforged.neoforge.network.payload.ModdedNetworkSetupFailedPayload;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
/**
diff --git a/src/main/java/net/neoforged/neoforge/network/registration/PayloadRegistrar.java b/src/main/java/net/neoforged/neoforge/network/registration/PayloadRegistrar.java
index 0d56264f108..4b20c164054 100644
--- a/src/main/java/net/neoforged/neoforge/network/registration/PayloadRegistrar.java
+++ b/src/main/java/net/neoforged/neoforge/network/registration/PayloadRegistrar.java
@@ -15,7 +15,7 @@
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.neoforged.neoforge.network.handling.IPayloadHandler;
import net.neoforged.neoforge.network.handling.MainThreadPayloadHandler;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* Builder-style helper for registering {@link CustomPacketPayload}s, used for modded networking.
diff --git a/src/main/java/net/neoforged/neoforge/registries/BaseMappedRegistry.java b/src/main/java/net/neoforged/neoforge/registries/BaseMappedRegistry.java
index d45401cc3e8..c1a78e0e64a 100644
--- a/src/main/java/net/neoforged/neoforge/registries/BaseMappedRegistry.java
+++ b/src/main/java/net/neoforged/neoforge/registries/BaseMappedRegistry.java
@@ -19,7 +19,7 @@
import net.neoforged.neoforge.registries.callback.RegistryCallback;
import net.neoforged.neoforge.registries.datamaps.DataMapType;
import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
public abstract class BaseMappedRegistry