diff --git a/api/src/main/java/com/noxcrew/noxesium/api/protocol/ProtocolVersion.java b/api/src/main/java/com/noxcrew/noxesium/api/protocol/ProtocolVersion.java index 5de1fec0..5b6ae0d4 100644 --- a/api/src/main/java/com/noxcrew/noxesium/api/protocol/ProtocolVersion.java +++ b/api/src/main/java/com/noxcrew/noxesium/api/protocol/ProtocolVersion.java @@ -10,7 +10,7 @@ public class ProtocolVersion { * of Noxesium is available on the client. The protocol version will increment every full release, as such * ít is recommended to work with >= comparisons. */ - public static final int VERSION = 11; + public static final int VERSION = 12; /** * The name space to use for Noxesium. diff --git a/api/src/main/java/com/noxcrew/noxesium/api/protocol/rule/EntityRuleIndices.java b/api/src/main/java/com/noxcrew/noxesium/api/protocol/rule/EntityRuleIndices.java index 024d6c00..88247130 100644 --- a/api/src/main/java/com/noxcrew/noxesium/api/protocol/rule/EntityRuleIndices.java +++ b/api/src/main/java/com/noxcrew/noxesium/api/protocol/rule/EntityRuleIndices.java @@ -11,8 +11,8 @@ public class EntityRuleIndices { public static final int DISABLE_BUBBLES = 0; /** - * Defines a color to use for a beam created by this entity. Applies only to guardian - * beams at this time. + * Defines a color to use for a beam created by this entity. Applies to guardian beams + * and end crystal beams. */ public static final int BEAM_COLOR = 1; @@ -27,4 +27,9 @@ public class EntityRuleIndices { * qib collisions. The regular width is seen as its width on the X-axis. */ public static final int QIB_WIDTH_Z = 3; + + /** + * Defines a color used in combination with [BEAM_COLOR] to create a linear fade. + */ + public static final int BEAM_COLOR_FADE = 4; } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/NoxesiumMod.java b/fabric/src/main/java/com/noxcrew/noxesium/NoxesiumMod.java index 29924863..5e45a92e 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/NoxesiumMod.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/NoxesiumMod.java @@ -1,7 +1,7 @@ package com.noxcrew.noxesium; import com.google.common.base.Preconditions; -import com.mojang.blaze3d.shaders.Program; +import com.mojang.blaze3d.shaders.CompiledShader; import com.noxcrew.noxesium.api.protocol.ClientSettings; import com.noxcrew.noxesium.api.protocol.ProtocolVersion; import com.noxcrew.noxesium.config.NoxesiumConfig; @@ -30,12 +30,10 @@ import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.profiling.ProfilerFiller; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -79,7 +77,7 @@ public class NoxesiumMod implements ClientModInitializer { * The mapping of cached shaders. */ @Nullable - private GameRenderer.ResourceCache cachedShaders = null; + private Map cachedShaders = null; private final NoxesiumConfig config = NoxesiumConfig.load(); private final Logger logger = LoggerFactory.getLogger("Noxesium"); @@ -109,7 +107,7 @@ public NoxesiumConfig getConfig() { * Returns a cache with all shaders in the Sodium namespace. */ @Nullable - public GameRenderer.ResourceCache getCachedShaders() { + public Map getCachedShaders() { return cachedShaders; } @@ -208,50 +206,49 @@ public void onInitializeClient() { // Listen to shaders that are loaded and cache them ResourceManagerHelper - .get(PackType.CLIENT_RESOURCES) - .registerReloadListener( - new SimpleResourceReloadListener() { - @Override - public ResourceLocation getFabricId() { - return ResourceLocation.fromNamespaceAndPath(ProtocolVersion.NAMESPACE, "shaders"); - } - - @Override - public CompletableFuture load(ResourceManager manager, ProfilerFiller profiler, Executor executor) { - return CompletableFuture.supplyAsync(() -> { - var map = manager.listResources( - "shaders", - folder -> { - // We include all namespaces because you need to be able to import shaders from elsewhere! - var s = folder.getPath(); - return s.endsWith(".json") - || s.endsWith(Program.Type.FRAGMENT.getExtension()) - || s.endsWith(Program.Type.VERTEX.getExtension()) - || s.endsWith(".glsl"); - } - ); - var map1 = new HashMap(); - map.forEach((key, value) -> { - try (InputStream inputstream = value.open()) { - byte[] abyte = inputstream.readAllBytes(); - map1.put(ResourceLocation.fromNamespaceAndPath(key.getNamespace(), key.getPath().substring("shaders/".length())), new Resource(value.source(), () -> new ByteArrayInputStream(abyte))); - } catch (Exception exception) { - getLogger().warn("Failed to read resource {}", key, exception); - } - }); - - // Save the shaders here instead of in apply so we go before any other resource re-loader! - cachedShaders = new GameRenderer.ResourceCache(manager, map1); - return null; - }); - } - - @Override - public CompletableFuture apply(Void data, ResourceManager manager, ProfilerFiller profiler, Executor executor) { - return CompletableFuture.completedFuture(null); - } - } - ); + .get(PackType.CLIENT_RESOURCES) + .registerReloadListener( + new SimpleResourceReloadListener() { + @Override + public ResourceLocation getFabricId() { + return ResourceLocation.fromNamespaceAndPath(ProtocolVersion.NAMESPACE, "shaders"); + } + + @Override + public CompletableFuture load(ResourceManager manager, Executor executor) { + return CompletableFuture.supplyAsync(() -> { + var map = manager.listResources( + "shaders", + folder -> { + // We include all namespaces because you need to be able to import shaders from elsewhere! + var s = folder.getPath(); + return s.endsWith(".json") + || CompiledShader.Type.byLocation(folder) != null + || s.endsWith(".glsl"); + } + ); + var cache = new HashMap(); + map.forEach((key, value) -> { + try (InputStream inputstream = value.open()) { + byte[] abyte = inputstream.readAllBytes(); + cache.put(ResourceLocation.fromNamespaceAndPath(key.getNamespace(), key.getPath().substring("shaders/".length())), new Resource(value.source(), () -> new ByteArrayInputStream(abyte))); + } catch (Exception exception) { + getLogger().warn("Failed to read resource {}", key, exception); + } + }); + + // Save the shaders here instead of in apply so we go before any other resource re-loader! + cachedShaders = cache; + return null; + }); + } + + @Override + public CompletableFuture apply(Void data, ResourceManager manager, Executor executor) { + return CompletableFuture.completedFuture(null); + } + } + ); // Run rebuilds on a separate thread to not destroy fps unnecessarily var rebuildThread = new Thread("Noxesium Spatial Container Rebuild Thread") { @@ -324,15 +321,15 @@ public static void syncGuiScale() { var options = Minecraft.getInstance().options; new ServerboundClientSettingsPacket( - new ClientSettings( - options.guiScale().get(), - window.getGuiScale(), - window.getGuiScaledWidth(), - window.getGuiScaledHeight(), - Minecraft.getInstance().isEnforceUnicode(), - options.touchscreen().get(), - options.notificationDisplayTime().get() - ) + new ClientSettings( + options.guiScale().get(), + window.getGuiScale(), + window.getGuiScaledWidth(), + window.getGuiScaledHeight(), + Minecraft.getInstance().isEnforceUnicode(), + options.touchscreen().get(), + options.notificationDisplayTime().get() + ) ).send(); } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/config/MapLocation.java b/fabric/src/main/java/com/noxcrew/noxesium/config/MapLocation.java index fa022518..c9a57330 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/config/MapLocation.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/config/MapLocation.java @@ -5,5 +5,21 @@ */ public enum MapLocation { TOP, - BOTTOM + BOTTOM, + TOP_FLIPPED, + BOTTOM_FLIPPED; + + /** + * Returns whether this location is on the bottom side. + */ + public boolean isBottom() { + return this == BOTTOM || this == BOTTOM_FLIPPED; + } + + /** + * Returns whether this location should be flipped. + */ + public boolean isFlipped() { + return this == TOP_FLIPPED || this == BOTTOM_FLIPPED; + } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ArmorStandCullingExtension.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ArmorStandCullingExtension.java new file mode 100644 index 00000000..3a482861 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ArmorStandCullingExtension.java @@ -0,0 +1,22 @@ +package com.noxcrew.noxesium.feature.entity; + +import net.minecraft.world.phys.AABB; + +/** + * Defines an extension for armor stand culling bounding boxes. + */ +public interface ArmorStandCullingExtension { + + /** + * Returns the culling bounding box. + */ + public default AABB noxesium$getCullingBoundingBox() { + throw new UnsupportedOperationException("Unimplemented"); + } + + /** + * Updates the culling bounding box. + */ + public default void noxesium$setCullingBoundingBox(AABB boundingBox) { + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/BeamColorStateExtension.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/BeamColorStateExtension.java new file mode 100644 index 00000000..ece7e454 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/BeamColorStateExtension.java @@ -0,0 +1,18 @@ +package com.noxcrew.noxesium.feature.entity; + +/** + * Extends the guardian and end crystal states with a beam color. + */ +public interface BeamColorStateExtension { + + default Integer noxesium$getBeamColor() { + throw new UnsupportedOperationException("Unimplemented"); + } + + default Integer noxesium$getBeamColorFade() { + throw new UnsupportedOperationException("Unimplemented"); + } + + default void noxesium$setBeamColor(Integer color, Integer fade) { + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/EndCrystalRenderHolder.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/EndCrystalRenderHolder.java new file mode 100644 index 00000000..6fe3205d --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/EndCrystalRenderHolder.java @@ -0,0 +1,21 @@ +package com.noxcrew.noxesium.feature.entity; + +/** + * Stores the color being used for rendering an end crystal beam. + */ +public class EndCrystalRenderHolder { + /** + * The current color being used when rendering end crystal beams. + */ + public static Integer noxesium$endCrystalBeamColor = null; + + /** + * The current fade color for the end crystal beams. + */ + public static Integer noxesium$endCrystalBeamColorFade = null; + + /** + * The current vertex index. + */ + public static int noxesium$index = 0; +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ExtraEntityData.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ExtraEntityData.java index 7916c6c9..515b1285 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ExtraEntityData.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/ExtraEntityData.java @@ -21,7 +21,8 @@ public class ExtraEntityData { public static ClientServerRule DISABLE_BUBBLES = register(new BooleanServerRule(EntityRuleIndices.DISABLE_BUBBLES, false)); /** - * If `true` bubbles are removed from guardian beams shot by this entity. + * Defines a color to use for a beam created by this entity. Applies to guardian beams + * and end crystal beams. */ public static ClientServerRule> BEAM_COLOR = register(new ColorServerRule(EntityRuleIndices.BEAM_COLOR, Optional.empty())); @@ -37,6 +38,11 @@ public class ExtraEntityData { */ public static ClientServerRule QIB_WIDTH_Z = register(new DoubleServerRule(EntityRuleIndices.QIB_WIDTH_Z, 1.0)); + /** + * Defines a color used in combination with [BEAM_COLOR] to create a linear fade. + */ + public static ClientServerRule> BEAM_COLOR_FADE = register(new ColorServerRule(EntityRuleIndices.BEAM_COLOR_FADE, Optional.empty())); + /** * Registers a new extra entity data key. */ diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/QibBehaviorModule.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/QibBehaviorModule.java index bb8bf589..7bd2fd39 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/QibBehaviorModule.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/QibBehaviorModule.java @@ -270,7 +270,7 @@ private void executeBehavior(LocalPlayer player, Entity entity, QibEffect effect ); } case QibEffect.GivePotionEffect giveEffect -> { - var type = BuiltInRegistries.MOB_EFFECT.getHolder(ResourceLocation.fromNamespaceAndPath(giveEffect.namespace(), giveEffect.path())).orElse(null); + var type = BuiltInRegistries.MOB_EFFECT.get(ResourceLocation.fromNamespaceAndPath(giveEffect.namespace(), giveEffect.path())).orElse(null); player.noxesium$addClientsidePotionEffect( new MobEffectInstance( type, @@ -283,7 +283,7 @@ private void executeBehavior(LocalPlayer player, Entity entity, QibEffect effect ); } case QibEffect.RemovePotionEffect removeEffect -> { - player.noxesium$removeClientsidePotionEffect(BuiltInRegistries.MOB_EFFECT.getHolder(ResourceLocation.fromNamespaceAndPath(removeEffect.namespace(), removeEffect.path())).orElse(null)); + player.noxesium$removeClientsidePotionEffect(BuiltInRegistries.MOB_EFFECT.get(ResourceLocation.fromNamespaceAndPath(removeEffect.namespace(), removeEffect.path())).orElse(null)); } case QibEffect.Move move -> { player.move(MoverType.SELF, new Vec3(move.x(), move.y(), move.z())); diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialDebuggingModule.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialDebuggingModule.java index 756e93e8..bd192bc3 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialDebuggingModule.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialDebuggingModule.java @@ -12,9 +12,9 @@ import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.client.renderer.CoreShaders; +import net.minecraft.client.renderer.ShapeRenderer; +import net.minecraft.util.profiling.Profiler; import org.lwjgl.opengl.GL32; import java.awt.Color; @@ -49,15 +49,15 @@ private void onRenderHook() { var models = SpatialInteractionEntityTree.getModelContents(); - Minecraft.getInstance().getProfiler().push("noxesium-debug"); + Profiler.get().push("noxesium-debug"); RenderSystem.disableCull(); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.depthMask(true); - final ShaderInstance oldShader = RenderSystem.getShader(); - RenderSystem.setShader(GameRenderer::getRendertypeLinesShader); + final var oldShader = RenderSystem.getShader(); + RenderSystem.setShader(CoreShaders.RENDERTYPE_LINES); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); var vec3 = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); @@ -73,7 +73,7 @@ private void onRenderHook() { // Start the buffer after setting up the depth settings var buffer = Tesselator.getInstance().begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL); try { - LevelRenderer.renderLineBox(poseStack, buffer, model, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1.0F); + ShapeRenderer.renderLineBox(poseStack, buffer, model, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1.0F); } catch (Exception x) { // Ignore exceptions from in here if (SharedConstants.IS_RUNNING_IN_IDE) throw x; @@ -86,10 +86,10 @@ private void onRenderHook() { } RenderSystem.depthFunc(GL32.GL_LEQUAL); - RenderSystem.setShader(() -> oldShader); + RenderSystem.setShader(oldShader); RenderSystem.disableBlend(); RenderSystem.enableCull(); - Minecraft.getInstance().getProfiler().pop(); + Profiler.get().pop(); } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialInteractionEntityTree.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialInteractionEntityTree.java index 8a92fed5..07a18dc7 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialInteractionEntityTree.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/entity/SpatialInteractionEntityTree.java @@ -107,8 +107,9 @@ public static void rebuild() { if (NoxesiumMod.getInstance().getConfig().enableQibSystemDebugging) { if (Minecraft.getInstance().player != null) { - Minecraft.getInstance().player.sendSystemMessage( - Component.literal("§eRebuilt spatial model, before: §f[" + oldStaticEntities + ", " + addedEntities.size() + ", " + removingEntities.size() + "]§e, after: §f[" + staticEntities.size() + ", " + pendingEntities.size() + ", " + removedEntities.size() + "]") + Minecraft.getInstance().getChatListener().handleSystemMessage( + Component.literal("§eRebuilt spatial model, before: §f[" + oldStaticEntities + ", " + addedEntities.size() + ", " + removingEntities.size() + "]§e, after: §f[" + staticEntities.size() + ", " + pendingEntities.size() + ", " + removedEntities.size() + "]"), + false ); } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomItemOverrides.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomBakedOverrides.java similarity index 89% rename from fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomItemOverrides.java rename to fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomBakedOverrides.java index 9329c9cb..e6e7dda1 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomItemOverrides.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/model/CustomBakedOverrides.java @@ -1,10 +1,10 @@ package com.noxcrew.noxesium.feature.model; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.renderer.block.model.BakedOverrides; import net.minecraft.client.renderer.block.model.ItemOverride; -import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.BlockModelRotation; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; @@ -24,12 +24,12 @@ /** * Determines if custom item overrides are solely for key/value mappings of custom model * data, in which case we build a hash map representation for them and use that instead. - * + *

* Will be removed in a future version as the model component now exists which should * be used if possible as it great performance for all clients. */ @Deprecated -public class CustomItemOverrides extends ItemOverrides { +public class CustomBakedOverrides extends BakedOverrides { /** * The maximum level of precision available. Any values beyond this @@ -63,8 +63,8 @@ public class CustomItemOverrides extends ItemOverrides { */ private Integer highestCustomModelData; - public CustomItemOverrides(ModelBaker modelBaker, BlockModel blockModel, List list) { - super(modelBaker, blockModel, list); + public CustomBakedOverrides(ModelBaker modelBaker, List list) { + super(modelBaker, list); // Ignore empty inputs if (list.isEmpty()) return; @@ -79,7 +79,7 @@ public CustomItemOverrides(ModelBaker modelBaker, BlockModel blockModel, List(null); - override.getPredicates().forEach(predicate -> { + override.predicates().forEach(predicate -> { // If we find any second element it's invalid if (first.getValue()) { invalid.setValue(true); @@ -90,8 +90,8 @@ public CustomItemOverrides(ModelBaker modelBaker, BlockModel blockModel, List bakeModel(modelBaker, blockModel, override)); + var bakedmodel = modelCache.computeIfAbsent(override.model(), (t) -> modelBaker.bake(t, BlockModelRotation.X0_Y0)); // Only create the hashmap if we're using it if (customModelDatas == null) { @@ -173,10 +173,10 @@ public CustomItemOverrides(ModelBaker modelBaker, BlockModel blockModel, List 1.0F) { + t = 1.0F; + } + + if (u > 1.0F) { + u = 1.0F; + } + + if (v > 1.0F) { + v = 1.0F; + } + + if (w > 1.0F) { + w = 1.0F; + } + + int x = (int) (t * 255.0F); + int y = (int) (u * 255.0F); + int z = (int) (v * 255.0F); + int aa = (int) (w * 255.0F); + image.setPixel(i, j, ARGB.color(aa, x, y, z)); + } + } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementBuffer.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementBuffer.java index dc221f73..85733159 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementBuffer.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementBuffer.java @@ -1,5 +1,6 @@ package com.noxcrew.noxesium.feature.ui.wrapper; +import com.mojang.blaze3d.buffers.BufferUsage; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.platform.GlStateManager; @@ -10,6 +11,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.CoreShaders; import net.minecraft.client.renderer.GameRenderer; import java.io.Closeable; @@ -68,7 +70,7 @@ public boolean resize(Window window) { } // Create a single texture that stretches the entirety of the buffer - var buffer = new VertexBuffer(VertexBuffer.Usage.STATIC); + var buffer = new VertexBuffer(BufferUsage.STATIC_WRITE); buffer.bind(); var builder = new BufferBuilder(new ByteBufferBuilder(4 * 6), VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); @@ -79,9 +81,9 @@ public boolean resize(Window window) { buffer.upload(builder.build()); if (target == null) { - target = new TextureTarget(width, height, true, ON_OSX); + target = new TextureTarget(width, height, true); } else { - target.resize(width, height, ON_OSX); + target.resize(width, height); } // Assign the buffer instance last! @@ -126,7 +128,7 @@ public void draw() { RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); }, () -> { - RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShader(CoreShaders.POSITION_TEX); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderTexture(0, getTextureId()); buffer.bind(); diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementWrapper.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementWrapper.java index 75ab5ccf..37a85e5d 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementWrapper.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/ElementWrapper.java @@ -77,6 +77,7 @@ */ public abstract class ElementWrapper { + private static final boolean DISABLE_SYSTEM = true; public static boolean allowBlendChanges = true; private final Map> variables = new HashMap<>(); @@ -160,8 +161,16 @@ public final void render(GuiGraphics graphics, DeltaTracker deltaTracker) { * Renders the UI element. */ public final void render(GuiGraphics graphics, DeltaTracker deltaTracker, @Nullable Runnable function) { - // Test if any variables have changed var minecraft = Minecraft.getInstance(); + + // Allow entirely disabling the system! + if (DISABLE_SYSTEM) { + if (function != null) function.run(); + render(graphics, minecraft, minecraft.getWindow().getGuiScaledWidth(), minecraft.getWindow().getGuiScaledHeight(), minecraft.font, deltaTracker); + return; + } + + // Test if any variables have changed testVariableChanges(minecraft, deltaTracker); try { @@ -186,7 +195,7 @@ public final void render(GuiGraphics graphics, DeltaTracker deltaTracker, @Nulla var target = buffer.getTarget(); try { target.setClearColor(0, 0, 0, 0); - target.clear(ON_OSX); + target.clear(); target.bindWrite(false); if (function != null) function.run(); render(graphics, minecraft, minecraft.getWindow().getGuiScaledWidth(), minecraft.getWindow().getGuiScaledHeight(), minecraft.font, deltaTracker); diff --git a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/MapUiWrapper.java b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/MapUiWrapper.java index 963a5fc6..debea15d 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/MapUiWrapper.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/feature/ui/wrapper/MapUiWrapper.java @@ -12,6 +12,7 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.state.MapRenderState; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; @@ -46,6 +47,8 @@ private static boolean hasMapItem(Minecraft minecraft, HumanoidArm arm) { return item.is(Items.FILLED_MAP) && (hand == InteractionHand.OFF_HAND || !otherHand.isEmpty()); } + private final MapRenderState mapRenderState = new MapRenderState(); + public MapUiWrapper() { // Update every tick for the map contents registerVariable("client tick", (minecraft, partialTicks) -> ((MinecraftExt) minecraft).getClientTickCount()); @@ -76,8 +79,11 @@ protected void render(GuiGraphics graphics, Minecraft minecraft, int screenWidth private void renderMap(Minecraft minecraft, GuiGraphics graphics, DeltaTracker deltaTracker, PoseStack pose, HumanoidArm arm, ItemStack item, int offset) { pose.pushPose(); var scale = 1f / ((float) minecraft.getWindow().getGuiScale()) * 4f * ((float) NoxesiumMod.getInstance().getConfig().mapUiSize); - var bottom = NoxesiumMod.getInstance().getConfig().mapUiLocation == MapLocation.BOTTOM; - if (arm == HumanoidArm.RIGHT) { + var setting = NoxesiumMod.getInstance().getConfig().mapUiLocation; + var bottom = setting.isBottom(); + var flipped = setting.isFlipped(); + + if ((arm == HumanoidArm.RIGHT) != flipped) { if (bottom) { // Translate it to be at the bottom right of the GUI pose.translate(graphics.guiWidth() - (148f * scale), graphics.guiHeight() - (148f * scale), 0f); @@ -97,20 +103,22 @@ private void renderMap(Minecraft minecraft, GuiGraphics graphics, DeltaTracker d pose.scale(1f * scale, 1f * scale, -1f); pose.translate(10f, 10f, 0f); - MapId mapid = item.get(DataComponents.MAP_ID); - MapItemSavedData mapitemsaveddata = MapItem.getSavedData(mapid, minecraft.level); - var bufferSource = graphics.bufferSource(); - VertexConsumer vertexconsumer = bufferSource.getBuffer(mapitemsaveddata == null ? MAP_BACKGROUND : MAP_BACKGROUND_CHECKERBOARD); - Matrix4f matrix4f = pose.last().pose(); - var light = minecraft.getEntityRenderDispatcher().getPackedLightCoords(minecraft.player, deltaTracker.getGameTimeDeltaPartialTick(true)); - vertexconsumer.addVertex(matrix4f, -7.0F, 135.0F, 0.0F).setColor(-1).setUv(0.0F, 1.0F).setLight(light); - vertexconsumer.addVertex(matrix4f, 135.0F, 135.0F, 0.0F).setColor(-1).setUv(1.0F, 1.0F).setLight(light); - vertexconsumer.addVertex(matrix4f, 135.0F, -7.0F, 0.0F).setColor(-1).setUv(1.0F, 0.0F).setLight(light); - vertexconsumer.addVertex(matrix4f, -7.0F, -7.0F, 0.0F).setColor(-1).setUv(0.0F, 0.0F).setLight(light); - if (mapitemsaveddata != null) { - minecraft.gameRenderer.getMapRenderer().render(pose, bufferSource, mapid, mapitemsaveddata, false, light); - } - bufferSource.endBatch(); + var mapId = item.get(DataComponents.MAP_ID); + var mapitemsaveddata = MapItem.getSavedData(mapId, minecraft.level); + graphics.drawSpecial(bufferSource -> { + VertexConsumer vertexconsumer = bufferSource.getBuffer(mapitemsaveddata == null ? MAP_BACKGROUND : MAP_BACKGROUND_CHECKERBOARD); + Matrix4f matrix4f = pose.last().pose(); + var light = minecraft.getEntityRenderDispatcher().getPackedLightCoords(minecraft.player, deltaTracker.getGameTimeDeltaPartialTick(true)); + vertexconsumer.addVertex(matrix4f, -7.0F, 135.0F, 0.0F).setColor(-1).setUv(0.0F, 1.0F).setLight(light); + vertexconsumer.addVertex(matrix4f, 135.0F, 135.0F, 0.0F).setColor(-1).setUv(1.0F, 1.0F).setLight(light); + vertexconsumer.addVertex(matrix4f, 135.0F, -7.0F, 0.0F).setColor(-1).setUv(1.0F, 0.0F).setLight(light); + vertexconsumer.addVertex(matrix4f, -7.0F, -7.0F, 0.0F).setColor(-1).setUv(0.0F, 0.0F).setLight(light); + if (mapitemsaveddata != null) { + var mapRenderer = minecraft.getMapRenderer(); + mapRenderer.extractRenderState(mapId, mapitemsaveddata, mapRenderState); + mapRenderer.render(mapRenderState, pose, bufferSource, false, light); + } + }); pose.popPose(); } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/EnableTabHatLayerMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/EnableTabHatLayerMixin.java index b3e21838..2d3aa714 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/EnableTabHatLayerMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/EnableTabHatLayerMixin.java @@ -14,7 +14,7 @@ @Mixin(PlayerTabOverlay.class) public abstract class EnableTabHatLayerMixin { - @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/PlayerFaceRenderer;draw(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/resources/ResourceLocation;IIIZZ)V"), index = 5) + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/PlayerFaceRenderer;draw(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/resources/ResourceLocation;IIIZZI)V"), index = 5) private boolean alwaysRenderHat(boolean original) { return true; } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/FixTextDisplayTransparencyMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/FixTextDisplayTransparencyMixin.java index b601a10c..d6e2149c 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/FixTextDisplayTransparencyMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/feature/FixTextDisplayTransparencyMixin.java @@ -16,7 +16,7 @@ public abstract class FixTextDisplayTransparencyMixin { * which fixes issues with its transparency. We do however use a custom type with a depth buffer that ensures the background does not * render through walls. We want to render things behind it, not it behind other things. */ - @Redirect(method = "renderInner(Lnet/minecraft/world/entity/Display$TextDisplay;Lnet/minecraft/world/entity/Display$TextDisplay$TextRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderType;textBackground()Lnet/minecraft/client/renderer/RenderType;")) + @Redirect(method = "renderInner(Lnet/minecraft/client/renderer/entity/state/TextDisplayEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderType;textBackground()Lnet/minecraft/client/renderer/RenderType;")) public RenderType determineRenderType() { return CustomRenderTypes.textBackgroundSeeThroughWithDepth(); } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/CustomItemOverridesMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/ReplaceBakedModelOverrides.java similarity index 54% rename from fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/CustomItemOverridesMixin.java rename to fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/ReplaceBakedModelOverrides.java index 928dd655..f454d492 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/CustomItemOverridesMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/ReplaceBakedModelOverrides.java @@ -1,9 +1,9 @@ package com.noxcrew.noxesium.mixin.legacy; -import com.noxcrew.noxesium.feature.model.CustomItemOverrides; -import net.minecraft.client.renderer.block.model.BlockModel; +import com.noxcrew.noxesium.feature.model.CustomBakedOverrides; +import net.minecraft.client.renderer.block.model.BakedOverrides; import net.minecraft.client.renderer.block.model.ItemOverride; -import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.resources.model.ItemModel; import net.minecraft.client.resources.model.ModelBaker; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -15,20 +15,20 @@ * Replaces vanilla custom item overrides whenever just CustomModelData is being used * to replace iterator over all overrides with a direct lookup. This greatly improves * performance when single items have large amounts of overrides. - * + *

* Will be removed in a future version as the model component now exists which should * be used if possible as it great performance for all clients. */ -@Mixin(value = BlockModel.class, priority = 500) +@Mixin(value = ItemModel.class, priority = 500) @Deprecated -public abstract class CustomItemOverridesMixin { +public abstract class ReplaceBakedModelOverrides { /** * @author Aeltumn * @reason Replace item overrides that solely contain custom model data values */ - @Redirect(method = "getItemOverrides", at = @At(value = "NEW", target = "(Lnet/minecraft/client/resources/model/ModelBaker;Lnet/minecraft/client/renderer/block/model/BlockModel;Ljava/util/List;)Lnet/minecraft/client/renderer/block/model/ItemOverrides;")) - public ItemOverrides replaceItemOverrides(ModelBaker baker, BlockModel model, List overrides) { - return new CustomItemOverrides(baker, model, overrides); + @Redirect(method = "bake", at = @At(value = "NEW", target = "(Lnet/minecraft/client/resources/model/ModelBaker;Ljava/util/List;)Lnet/minecraft/client/renderer/block/model/BakedOverrides;")) + public BakedOverrides replaceItemOverrides(ModelBaker modelBaker, List overrides) { + return new CustomBakedOverrides(modelBaker, overrides); } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingMixin.java index 4c3ace18..6c7eda8f 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingMixin.java @@ -1,66 +1,42 @@ package com.noxcrew.noxesium.mixin.legacy.culling; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.noxcrew.noxesium.NoxesiumMod; -import com.noxcrew.noxesium.feature.entity.QibBehaviorModule; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.entity.layers.CustomHeadLayer; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.core.Rotations; +import com.noxcrew.noxesium.feature.entity.ArmorStandCullingExtension; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.joml.Vector4f; -import org.lwjgl.system.MemoryStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.util.List; import java.util.Objects; /** * Update the culling bounding box for armor stands to include the hitbox of the model on their head or arms. - * + *

* Will be removed in a future version as using armor stands for models is * no longer recommended, use display entities instead which let you customise * the culling hitbox. */ @Mixin(LivingEntity.class) @Deprecated -public abstract class ArmorStandCullingMixin { +public abstract class ArmorStandCullingMixin implements ArmorStandCullingExtension { @Unique private AABB noxesium$cullingBoundingBox; - @Unique - private float noxesium$lastYBodyRot = 0f; - @Unique - private long noxesium$lastRender = 0; - @Inject(method = "jumpFromGround", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;")) - public void onJumpFromGround(CallbackInfo ci) { - var entity = (LivingEntity) ((Object) this); - if (entity instanceof LocalPlayer localPlayer) { - NoxesiumMod.getInstance().getModule(QibBehaviorModule.class).onPlayerJump(localPlayer); - } + @Override + public AABB noxesium$getCullingBoundingBox() { + return noxesium$cullingBoundingBox; + } + + @Override + public void noxesium$setCullingBoundingBox(AABB boundingBox) { + noxesium$cullingBoundingBox = boundingBox; } @Inject(method = "onSyncedDataUpdated", at = @At("RETURN")) @@ -85,158 +61,4 @@ public void updateBoundingBoxOnEquip(EquipmentSlot equipmentSlot, ItemStack item noxesium$cullingBoundingBox = null; } } - - @Inject(method = "getBoundingBoxForCulling", at = @At("HEAD"), cancellable = true) - public void extendedBoundingBoxToIncludeNoxesiumModel(CallbackInfoReturnable cir) { - if (((Entity) (Object) this) instanceof ArmorStand armorStand) { - // Invalidate if the y rotation changed - if (Math.abs(noxesium$lastYBodyRot - armorStand.yBodyRot) > 0.1) { - noxesium$cullingBoundingBox = null; - } - - // Re-calculate the bounding box if necessary (and not more than once per second) - if (noxesium$cullingBoundingBox == null && (System.currentTimeMillis() - noxesium$lastRender) >= 1000) { - noxesium$lastRender = System.currentTimeMillis(); - noxesium$lastYBodyRot = armorStand.yBodyRot; - noxesium$cullingBoundingBox = noxesium$updateBoundingBox(armorStand); - } - if (noxesium$cullingBoundingBox != null) { - cir.setReturnValue(noxesium$cullingBoundingBox.move(((Entity) (Object) this).position())); - } - } - } - - /** - * Recalculates the bounding box for [armorStand]. - */ - @Unique - private AABB noxesium$updateBoundingBox(ArmorStand armorStand) { - // Only go through this entity if it has some item in its hand or head slot - if (armorStand.hasItemInSlot(EquipmentSlot.HEAD) || - armorStand.hasItemInSlot(EquipmentSlot.MAINHAND) || - armorStand.hasItemInSlot(EquipmentSlot.OFFHAND)) { - - var boundingBox = AABB.ofSize(Vec3.ZERO, 0, 0, 0); - var itemRenderer = Minecraft.getInstance().getItemRenderer(); - var randomSource = RandomSource.create(42); - var poseStack = new PoseStack(); - - // Set up the pose stack - poseStack.mulPose(Axis.YP.rotationDegrees(180f - armorStand.yBodyRot)); - poseStack.scale(-1.0F, -1.0F, 1.0F); - poseStack.translate(0.0D, (double) -1.501F, 0.0D); - - // Determine which items are being held - var flag = armorStand.getMainArm() == HumanoidArm.LEFT; - var leftItem = flag ? armorStand.getMainHandItem() : armorStand.getOffhandItem(); - var rightItem = flag ? armorStand.getOffhandItem() : armorStand.getMainHandItem(); - - // Determine which item model we're using - BakedModel itemModel = null; - - // Try out the head item - if (armorStand.hasItemInSlot(EquipmentSlot.HEAD)) { - // Set up the pose stack for drawing the model - var item = armorStand.getItemBySlot(EquipmentSlot.HEAD); - itemModel = itemRenderer.getModel(item, armorStand.level(), armorStand, 0); - - // Rotate the bounding box following the rotation of the entity - var pose = armorStand.getEntityData().get(ArmorStand.DATA_HEAD_POSE); - noxesium$setRotations(poseStack, pose); - CustomHeadLayer.translateToHead(poseStack, false); - itemModel.getTransforms().getTransform(ItemDisplayContext.HEAD).apply(false, poseStack); - poseStack.translate(-0.5D, -0.5D, -0.5D); - } - - // Try the hand items - else if (!leftItem.isEmpty() || !rightItem.isEmpty()) { - // Rotate the bounding box following the rotation of the entity - var flag2 = rightItem.isEmpty(); - var pose = armorStand.getEntityData().get(flag2 ? ArmorStand.DATA_LEFT_ARM_POSE : ArmorStand.DATA_RIGHT_ARM_POSE); - if (flag2) { - poseStack.translate(5.0 / 16.0, 0.0, 0.0); - } else { - poseStack.translate(-5.0 / 16.0, 0.0, 0.0); - } - noxesium$setRotations(poseStack, pose); - - poseStack.mulPose(Axis.XP.rotationDegrees(-90.0F)); - poseStack.mulPose(Axis.YP.rotationDegrees(180.0F)); - poseStack.translate((float) (flag2 ? -1 : 1) / 16.0F, 0.125D, -0.625D); - itemModel = itemRenderer.getModel(flag2 ? leftItem : rightItem, armorStand.level(), armorStand, 0); - } - - // If there is no item model we return - if (itemModel == null) return boundingBox; - - var memorystack = MemoryStack.stackPush(); - var bytebuffer = memorystack.malloc(DefaultVertexFormat.BLOCK.getVertexSize()); - var intbuffer = bytebuffer.asIntBuffer(); - - // Go through all quads and extend the bounding box - for (var direction : Direction.values()) { - var quads = itemModel.getQuads(null, direction, randomSource); - boundingBox = noxesium$iterateQuads(poseStack, boundingBox, bytebuffer, intbuffer, quads); - } - var quads = itemModel.getQuads(null, null, randomSource); - boundingBox = noxesium$iterateQuads(poseStack, boundingBox, bytebuffer, intbuffer, quads); - memorystack.close(); - - return boundingBox; - } - return null; - } - - @Unique - private void noxesium$setRotations(PoseStack poseStack, Rotations pose) { - var xRot = ((float) Math.PI / 180F) * pose.getX(); - var yRot = ((float) Math.PI / 180F) * pose.getY(); - var zRot = ((float) Math.PI / 180F) * pose.getZ(); - if (zRot != 0.0F) { - poseStack.mulPose(Axis.ZP.rotation(zRot)); - } - if (yRot != 0.0F) { - poseStack.mulPose(Axis.YP.rotation(yRot)); - } - if (xRot != 0.0F) { - poseStack.mulPose(Axis.XP.rotation(xRot)); - } - } - - /** - * Iterate through all quads in the int buffer to update the bounding box. - */ - @Unique - private static AABB noxesium$iterateQuads(PoseStack poseStack, AABB boundingBox, ByteBuffer bytebuffer, IntBuffer intbuffer, List quads) { - var matrix4f = poseStack.last().pose(); - for (var quad : quads) { - int j = quad.getVertices().length / 8; - for (int k = 0; k < j; ++k) { - intbuffer.clear(); - intbuffer.put(quad.getVertices(), k * 8, 8); - float f = bytebuffer.getFloat(0); - float f1 = bytebuffer.getFloat(4); - float f2 = bytebuffer.getFloat(8); - boundingBox = noxesium$expandToInclude(boundingBox, matrix4f.transform(new Vector4f(f, f1, f2, 1.0F))); - } - } - return boundingBox; - } - - /** - * Expands the given [boundingBox] if necessary to include [vector]. - */ - @Unique - private static AABB noxesium$expandToInclude(AABB boundingBox, Vector4f vector) { - // Avoid creating a new object if possible - if (boundingBox.contains(vector.x(), vector.y(), vector.z())) return boundingBox; - - double d = Math.min(boundingBox.minX, vector.x()); - double e = Math.min(boundingBox.minY, vector.y()); - double f = Math.min(boundingBox.minZ, vector.z()); - double g = Math.max(boundingBox.maxX, vector.x()); - double h = Math.max(boundingBox.maxY, vector.y()); - double i = Math.max(boundingBox.maxZ, vector.z()); - return new AABB(d, e, f, g, h, i); - } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingRenderMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingRenderMixin.java new file mode 100644 index 00000000..6a297a54 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/legacy/culling/ArmorStandCullingRenderMixin.java @@ -0,0 +1,203 @@ +package com.noxcrew.noxesium.mixin.legacy.culling; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.layers.CustomHeadLayer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.core.Rotations; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector4f; +import org.lwjgl.system.MemoryStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.List; + +/** + * Update the culling bounding box for armor stands to include the hitbox of the model on their head or arms. + *

+ * Will be removed in a future version as using armor stands for models is + * no longer recommended, use display entities instead which let you customise + * the culling hitbox. + */ +@Mixin(LivingEntityRenderer.class) +@Deprecated +public abstract class ArmorStandCullingRenderMixin { + + @Unique + private float noxesium$lastYBodyRot = 0f; + @Unique + private long noxesium$lastRender = 0; + + @Inject(method = "getBoundingBoxForCulling(Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/phys/AABB;", at = @At("HEAD"), cancellable = true) + public void extendedBoundingBoxToIncludeNoxesiumModel(LivingEntity entity, CallbackInfoReturnable cir) { + if (entity instanceof ArmorStand armorStand) { + // Invalidate if the y rotation changed + if (Math.abs(noxesium$lastYBodyRot - armorStand.yBodyRot) > 0.1) { + armorStand.noxesium$setCullingBoundingBox(null); + } + + // Re-calculate the bounding box if necessary (and not more than once per second) + if (armorStand.noxesium$getCullingBoundingBox() == null && (System.currentTimeMillis() - noxesium$lastRender) >= 1000) { + noxesium$lastRender = System.currentTimeMillis(); + noxesium$lastYBodyRot = armorStand.yBodyRot; + armorStand.noxesium$setCullingBoundingBox(noxesium$updateBoundingBox(armorStand)); + } + if (armorStand.noxesium$getCullingBoundingBox() != null) { + cir.setReturnValue(armorStand.noxesium$getCullingBoundingBox().move(((Entity) (Object) this).position())); + } + } + } + + /** + * Recalculates the bounding box for [armorStand]. + */ + @Unique + private AABB noxesium$updateBoundingBox(ArmorStand armorStand) { + // Only go through this entity if it has some item in its hand or head slot + if (armorStand.hasItemInSlot(EquipmentSlot.HEAD) || + armorStand.hasItemInSlot(EquipmentSlot.MAINHAND) || + armorStand.hasItemInSlot(EquipmentSlot.OFFHAND)) { + + var boundingBox = AABB.ofSize(Vec3.ZERO, 0, 0, 0); + var itemRenderer = Minecraft.getInstance().getItemRenderer(); + var randomSource = RandomSource.create(42); + var poseStack = new PoseStack(); + + // Set up the pose stack + poseStack.mulPose(Axis.YP.rotationDegrees(180f - armorStand.yBodyRot)); + poseStack.scale(-1.0F, -1.0F, 1.0F); + poseStack.translate(0.0D, (double) -1.501F, 0.0D); + + // Determine which items are being held + var flag = armorStand.getMainArm() == HumanoidArm.LEFT; + var leftItem = flag ? armorStand.getMainHandItem() : armorStand.getOffhandItem(); + var rightItem = flag ? armorStand.getOffhandItem() : armorStand.getMainHandItem(); + + // Determine which item model we're using + BakedModel itemModel = null; + + // Try out the head item + if (armorStand.hasItemInSlot(EquipmentSlot.HEAD)) { + // Set up the pose stack for drawing the model + var item = armorStand.getItemBySlot(EquipmentSlot.HEAD); + itemModel = itemRenderer.getModel(item, armorStand.level(), armorStand, 0); + + // Rotate the bounding box following the rotation of the entity + var pose = armorStand.getEntityData().get(ArmorStand.DATA_HEAD_POSE); + noxesium$setRotations(poseStack, pose); + CustomHeadLayer.translateToHead(poseStack, CustomHeadLayer.Transforms.DEFAULT); + itemModel.getTransforms().getTransform(ItemDisplayContext.HEAD).apply(false, poseStack); + poseStack.translate(-0.5D, -0.5D, -0.5D); + } + + // Try the hand items + else if (!leftItem.isEmpty() || !rightItem.isEmpty()) { + // Rotate the bounding box following the rotation of the entity + var flag2 = rightItem.isEmpty(); + var pose = armorStand.getEntityData().get(flag2 ? ArmorStand.DATA_LEFT_ARM_POSE : ArmorStand.DATA_RIGHT_ARM_POSE); + if (flag2) { + poseStack.translate(5.0 / 16.0, 0.0, 0.0); + } else { + poseStack.translate(-5.0 / 16.0, 0.0, 0.0); + } + noxesium$setRotations(poseStack, pose); + + poseStack.mulPose(Axis.XP.rotationDegrees(-90.0F)); + poseStack.mulPose(Axis.YP.rotationDegrees(180.0F)); + poseStack.translate((float) (flag2 ? -1 : 1) / 16.0F, 0.125D, -0.625D); + itemModel = itemRenderer.getModel(flag2 ? leftItem : rightItem, armorStand.level(), armorStand, 0); + } + + // If there is no item model we return + if (itemModel == null) return boundingBox; + + var memorystack = MemoryStack.stackPush(); + var bytebuffer = memorystack.malloc(DefaultVertexFormat.BLOCK.getVertexSize()); + var intbuffer = bytebuffer.asIntBuffer(); + + // Go through all quads and extend the bounding box + for (var direction : Direction.values()) { + var quads = itemModel.getQuads(null, direction, randomSource); + boundingBox = noxesium$iterateQuads(poseStack, boundingBox, bytebuffer, intbuffer, quads); + } + var quads = itemModel.getQuads(null, null, randomSource); + boundingBox = noxesium$iterateQuads(poseStack, boundingBox, bytebuffer, intbuffer, quads); + memorystack.close(); + + return boundingBox; + } + return null; + } + + @Unique + private void noxesium$setRotations(PoseStack poseStack, Rotations pose) { + var xRot = ((float) Math.PI / 180F) * pose.getX(); + var yRot = ((float) Math.PI / 180F) * pose.getY(); + var zRot = ((float) Math.PI / 180F) * pose.getZ(); + if (zRot != 0.0F) { + poseStack.mulPose(Axis.ZP.rotation(zRot)); + } + if (yRot != 0.0F) { + poseStack.mulPose(Axis.YP.rotation(yRot)); + } + if (xRot != 0.0F) { + poseStack.mulPose(Axis.XP.rotation(xRot)); + } + } + + /** + * Iterate through all quads in the int buffer to update the bounding box. + */ + @Unique + private static AABB noxesium$iterateQuads(PoseStack poseStack, AABB boundingBox, ByteBuffer bytebuffer, IntBuffer intbuffer, List quads) { + var matrix4f = poseStack.last().pose(); + for (var quad : quads) { + int j = quad.getVertices().length / 8; + for (int k = 0; k < j; ++k) { + intbuffer.clear(); + intbuffer.put(quad.getVertices(), k * 8, 8); + float f = bytebuffer.getFloat(0); + float f1 = bytebuffer.getFloat(4); + float f2 = bytebuffer.getFloat(8); + boundingBox = noxesium$expandToInclude(boundingBox, matrix4f.transform(new Vector4f(f, f1, f2, 1.0F))); + } + } + return boundingBox; + } + + /** + * Expands the given [boundingBox] if necessary to include [vector]. + */ + @Unique + private static AABB noxesium$expandToInclude(AABB boundingBox, Vector4f vector) { + // Avoid creating a new object if possible + if (boundingBox.contains(vector.x(), vector.y(), vector.z())) return boundingBox; + + double d = Math.min(boundingBox.minX, vector.x()); + double e = Math.min(boundingBox.minY, vector.y()); + double f = Math.min(boundingBox.minZ, vector.z()); + double g = Math.max(boundingBox.maxX, vector.x()); + double h = Math.max(boundingBox.maxY, vector.y()); + double i = Math.max(boundingBox.maxZ, vector.z()); + return new AABB(d, e, f, g, h, i); + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/BoatCollisionMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/BoatCollisionMixin.java index bae1003c..85c486cd 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/BoatCollisionMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/BoatCollisionMixin.java @@ -2,6 +2,7 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.noxcrew.noxesium.feature.rule.ServerRules; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.entity.vehicle.Boat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,7 +14,7 @@ * A similar server-side patch is required for it to be fully usable, for example: * BoatHider by TrollsterCooleg */ -@Mixin(Boat.class) +@Mixin(AbstractBoat.class) public abstract class BoatCollisionMixin { @ModifyReturnValue(method = "canCollideWith", at = @At("RETURN")) diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/HandItemOverrideRenderMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/HandItemOverrideRenderMixin.java index 2e164802..59cad0d3 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/HandItemOverrideRenderMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/HandItemOverrideRenderMixin.java @@ -1,27 +1,27 @@ package com.noxcrew.noxesium.mixin.rules; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.noxcrew.noxesium.feature.rule.InventoryHelper; -import net.minecraft.client.renderer.entity.layers.ItemInHandLayer; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; /** * Overrides the item shown as being held in the main hand on the 3d player model. */ -@Mixin(ItemInHandLayer.class) +@Mixin(LivingEntityRenderer.class) public abstract class HandItemOverrideRenderMixin { - @WrapOperation(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getMainHandItem()Lnet/minecraft/world/item/ItemStack;")) - public ItemStack getSelected(LivingEntity instance, Operation original) { - if (instance instanceof Player player) { + @Redirect(method = "extractRenderState(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getItemHeldByArm(Lnet/minecraft/world/entity/HumanoidArm;)Lnet/minecraft/world/item/ItemStack;")) + public ItemStack getItemByArm(LivingEntity instance, HumanoidArm humanoidArm) { + if (instance instanceof Player player && humanoidArm == player.getMainArm()) { return InventoryHelper.getRealSelected(player.getInventory()); } else { - return original.call(instance); + return instance.getItemHeldByArm(humanoidArm); } } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalBeamRendererMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalBeamRendererMixin.java new file mode 100644 index 00000000..83857e40 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalBeamRendererMixin.java @@ -0,0 +1,56 @@ +package com.noxcrew.noxesium.mixin.rules.entity; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EnderDragonRenderer; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import static com.noxcrew.noxesium.feature.entity.EndCrystalRenderHolder.noxesium$endCrystalBeamColor; +import static com.noxcrew.noxesium.feature.entity.EndCrystalRenderHolder.noxesium$endCrystalBeamColorFade; +import static com.noxcrew.noxesium.feature.entity.EndCrystalRenderHolder.noxesium$index; + +/** + * Hooks into end crystal beam rendering. + */ +@Mixin(EnderDragonRenderer.class) +public class EndCrystalBeamRendererMixin { + + /** + * Swap out the type of rendering for a transparent one so we can properly make it transparent. + */ + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderType;entitySmoothCutout(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/renderer/RenderType;")) + private static RenderType determineRenderType(ResourceLocation resourceLocation) { + return RenderType.entityTranslucent(resourceLocation, true); + } + + /** + * Override the vertex color used when drawing. + */ + @Redirect(method = "renderCrystalBeams", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/VertexConsumer;setColor(I)Lcom/mojang/blaze3d/vertex/VertexConsumer;")) + private static VertexConsumer overrideColor( + VertexConsumer vertexConsumer, int i + ) { + if (noxesium$endCrystalBeamColor != null) { + if (noxesium$endCrystalBeamColorFade != null) { + var ind = noxesium$index; + noxesium$index++; + if (noxesium$index >= 4) { + noxesium$index = 0; + } + if (ind == 0 || ind == 3) { + vertexConsumer.setColor(noxesium$endCrystalBeamColorFade); + } else { + vertexConsumer.setColor(noxesium$endCrystalBeamColor); + } + } else { + vertexConsumer.setColor(noxesium$endCrystalBeamColor); + } + } else { + vertexConsumer.setColor(i); + } + return vertexConsumer; + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalRendererMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalRendererMixin.java new file mode 100644 index 00000000..b783b866 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/EndCrystalRendererMixin.java @@ -0,0 +1,41 @@ +package com.noxcrew.noxesium.mixin.rules.entity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.noxcrew.noxesium.feature.entity.EndCrystalRenderHolder; +import com.noxcrew.noxesium.feature.entity.ExtraEntityData; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EndCrystalRenderer; +import net.minecraft.client.renderer.entity.state.EndCrystalRenderState; +import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.awt.Color; + +/** + * Hooks into the end crystal rendering. + */ +@Mixin(EndCrystalRenderer.class) +public class EndCrystalRendererMixin { + + /** + * Prepare the color when we begin rendering. + */ + @Inject(method = "render(Lnet/minecraft/client/renderer/entity/state/EndCrystalRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("HEAD")) + private void prepareColor(EndCrystalRenderState endCrystalRenderState, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) { + EndCrystalRenderHolder.noxesium$endCrystalBeamColor = endCrystalRenderState.noxesium$getBeamColor(); + EndCrystalRenderHolder.noxesium$endCrystalBeamColorFade = endCrystalRenderState.noxesium$getBeamColorFade(); + } + + /** + * Sets the current beam color on the render state. + */ + @Inject(method = "extractRenderState(Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;Lnet/minecraft/client/renderer/entity/state/EndCrystalRenderState;F)V", at = @At("RETURN")) + public void includeBeamInformation(EndCrystal endCrystal, EndCrystalRenderState endCrystalRenderState, float f, CallbackInfo ci) { + var color = endCrystal.noxesium$getExtraData(ExtraEntityData.BEAM_COLOR).map(Color::getRGB).orElse(null); + var fade = endCrystal.noxesium$getExtraData(ExtraEntityData.BEAM_COLOR_FADE).map(Color::getRGB).orElse(null); + endCrystalRenderState.noxesium$setBeamColor(color, fade); + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianBeamColorRendererMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianBeamColorRendererMixin.java index 4fa6bf88..3622effe 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianBeamColorRendererMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianBeamColorRendererMixin.java @@ -1,19 +1,23 @@ package com.noxcrew.noxesium.mixin.rules.entity; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.noxcrew.noxesium.feature.entity.ExtraEntityData; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.GuardianRenderer; -import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.entity.state.GuardianRenderState; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.monster.Guardian; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.awt.Color; /** * Hooks into the guardian rendering code to allow the color and alpha value of them to be changed. @@ -21,6 +25,25 @@ @Mixin(GuardianRenderer.class) public class GuardianBeamColorRendererMixin { + @Unique + private static Integer noxesium$beamColor = null; + + @Unique + private static Integer noxesium$beamColorFade = null; + + @Unique + private static int noxesium$index = 0; + + /** + * Sets the current beam color on the render state. + */ + @Inject(method = "extractRenderState(Lnet/minecraft/world/entity/monster/Guardian;Lnet/minecraft/client/renderer/entity/state/GuardianRenderState;F)V", at = @At("RETURN")) + public void includeBeamInformation(Guardian guardian, GuardianRenderState guardianRenderState, float f, CallbackInfo ci) { + var color = guardian.noxesium$getExtraData(ExtraEntityData.BEAM_COLOR).map(Color::getRGB).orElse(null); + var fade = guardian.noxesium$getExtraData(ExtraEntityData.BEAM_COLOR_FADE).map(Color::getRGB).orElse(null); + guardianRenderState.noxesium$setBeamColor(color, fade); + } + /** * Swap out the type of rendering for a transparent one so we can properly make it transparent. */ @@ -30,41 +53,40 @@ private static RenderType determineRenderType(ResourceLocation resourceLocation) } /** - * Override all vertex drawing so we can modify the color and alpha value. + * Prepare the color when we begin rendering. */ - @WrapOperation(method = "render(Lnet/minecraft/world/entity/monster/Guardian;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/GuardianRenderer;vertex(Lcom/mojang/blaze3d/vertex/VertexConsumer;Lcom/mojang/blaze3d/vertex/PoseStack$Pose;FFFIIIFF)V")) - private void overrideColor( - VertexConsumer vertexConsumer, - PoseStack.Pose pose, - float x, - float y, - float z, - int r, - int g, - int b, - float u, - float v, - Operation original, - Guardian guardian, - float f, - float partialTicks, - PoseStack poseStack, - MultiBufferSource bufferSource, - int light) { - - vertexConsumer.addVertex(pose, x, y, z); + @Inject(method = "render(Lnet/minecraft/client/renderer/entity/state/GuardianRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("HEAD")) + private void prepareColor(GuardianRenderState guardianRenderState, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) { + noxesium$beamColor = guardianRenderState.noxesium$getBeamColor(); + noxesium$beamColorFade = guardianRenderState.noxesium$getBeamColorFade(); + noxesium$index = 0; + } - // Load the color of the beam from the beam color data - var color = guardian.noxesium$getExtraData(ExtraEntityData.BEAM_COLOR); - if (color.isPresent()) { - vertexConsumer.setColor(color.get().getRGB()); + /** + * Override the vertex color used when drawing. + */ + @Redirect(method = "vertex", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/VertexConsumer;setColor(IIII)Lcom/mojang/blaze3d/vertex/VertexConsumer;")) + private static VertexConsumer overrideColor( + VertexConsumer vertexConsumer, int r, int g, int b, int a + ) { + if (noxesium$beamColor != null) { + if (noxesium$beamColorFade != null) { + var ind = noxesium$index; + noxesium$index++; + if (noxesium$index >= 12) { + noxesium$index = 0; + } + if (ind == 0 || ind == 3 || ind == 4 || ind >= 7) { + vertexConsumer.setColor(noxesium$beamColorFade); + } else { + vertexConsumer.setColor(noxesium$beamColor); + } + } else { + vertexConsumer.setColor(noxesium$beamColor); + } } else { vertexConsumer.setColor(r, g, b, 255); } - - vertexConsumer.setUv(u, v) - .setOverlay(OverlayTexture.NO_OVERLAY) - .setLight(15728880) - .setNormal(pose, 0.0F, 1.0F, 0.0F); + return vertexConsumer; } } diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianStateMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianStateMixin.java new file mode 100644 index 00000000..ee242804 --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/entity/GuardianStateMixin.java @@ -0,0 +1,36 @@ +package com.noxcrew.noxesium.mixin.rules.entity; + +import com.noxcrew.noxesium.feature.entity.BeamColorStateExtension; +import net.minecraft.client.renderer.entity.state.EndCrystalRenderState; +import net.minecraft.client.renderer.entity.state.GuardianRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +/** + * Implements the beam color state extension. + */ +@Mixin(value = {GuardianRenderState.class, EndCrystalRenderState.class}) +public class GuardianStateMixin implements BeamColorStateExtension { + + @Unique + private Integer noxesium$baseColor; + + @Unique + private Integer noxesium$fadeColor; + + @Override + public Integer noxesium$getBeamColor() { + return noxesium$baseColor; + } + + @Override + public Integer noxesium$getBeamColorFade() { + return noxesium$fadeColor; + } + + @Override + public void noxesium$setBeamColor(Integer color, Integer fade) { + this.noxesium$baseColor = color; + this.noxesium$fadeColor = fade; + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/JumpHookMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/JumpHookMixin.java new file mode 100644 index 00000000..3c2c01cd --- /dev/null +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/JumpHookMixin.java @@ -0,0 +1,25 @@ +package com.noxcrew.noxesium.mixin.rules.qib; + +import com.noxcrew.noxesium.NoxesiumMod; +import com.noxcrew.noxesium.feature.entity.QibBehaviorModule; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Hooks into a player jumping, triggers qib effects. + */ +@Mixin(LivingEntity.class) +public abstract class JumpHookMixin { + + @Inject(method = "jumpFromGround", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;")) + public void onJumpFromGround(CallbackInfo ci) { + var entity = (LivingEntity) ((Object) this); + if (entity instanceof LocalPlayer localPlayer) { + NoxesiumMod.getInstance().getModule(QibBehaviorModule.class).onPlayerJump(localPlayer); + } + } +} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/QibDebugRenderingMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/QibDebugRenderingMixin.java index 0cc0f00c..936fa826 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/QibDebugRenderingMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/qib/QibDebugRenderingMixin.java @@ -10,7 +10,9 @@ import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.ShapeRenderer; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -26,8 +28,8 @@ @Mixin(EntityRenderDispatcher.class) public class QibDebugRenderingMixin { - @Inject(method = "render", at = @At("TAIL")) - private void render(Entity entity, double d, double e, double f, float g, float partialTicks, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) { + @Inject(method = "render(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/renderer/entity/EntityRenderer;)V", at = @At("TAIL")) + private void render(Entity entity, double d, double e, double f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, EntityRenderer entityRenderer, CallbackInfo ci) { var entityRenderDispatcher = ((EntityRenderDispatcher) (Object) this); if (!NoxesiumMod.getInstance().getConfig().enableQibSystemDebugging) return; @@ -48,9 +50,9 @@ private void render(Entity entity, double d, double e, double f, float g, float if (qibBehavior != null) { var seededRandom = new Random(qibBehavior.hashCode()); var color = new Color(seededRandom.nextInt()); - LevelRenderer.renderLineBox(poseStack, noDepthBuffer, aabb, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 0.5F); + ShapeRenderer.renderLineBox(poseStack, noDepthBuffer, aabb, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 0.5F); var buffer = multiBufferSource.getBuffer(RenderType.lines()); - LevelRenderer.renderLineBox(poseStack, buffer, aabb, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1.0F); + ShapeRenderer.renderLineBox(poseStack, buffer, aabb, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1.0F); } // Draw a name tag based on the state of this entity in the spatial tree diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/trident/TridentHandModelMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/trident/TridentHandModelMixin.java index 7d17385e..9e4967b5 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/trident/TridentHandModelMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/rules/trident/TridentHandModelMixin.java @@ -13,7 +13,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.UseAnim; +import net.minecraft.world.item.ItemUseAnimation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -50,7 +50,7 @@ public void renderArmWithItem(AbstractClientPlayer p_109372_, float p_109373_, f // Ignore if charging an item beyond the first 50% if (p_109372_.isUsingItem() && p_109372_.getUseItemRemainingTicks() > 0 && p_109372_.getUsedItemHand() == p_109375_) { - if (p_109377_.getUseAnimation() != UseAnim.SPEAR) return; + if (p_109377_.getUseAnimation() != ItemUseAnimation.SPEAR) return; float f7 = (float) p_109377_.getUseDuration(p_109372_) - ((float) p_109372_.getUseItemRemainingTicks() - p_109373_ + 1.0F); float f11 = f7 / 10.0F; diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/settings/MissingTagExceptionMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/settings/MissingTagExceptionMixin.java deleted file mode 100644 index e8588776..00000000 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/settings/MissingTagExceptionMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.noxcrew.noxesium.mixin.settings; - -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.noxcrew.noxesium.NoxesiumMod; -import net.minecraft.core.HolderSet; -import net.minecraft.core.MappedRegistry; -import net.minecraft.tags.TagKey; -import org.spongepowered.asm.mixin.Mixin; - -import java.util.Optional; - -/** - * Hooks into getting tags and reports if any don't exist. - */ -@Mixin(MappedRegistry.class) -public class MissingTagExceptionMixin { - - @WrapMethod(method = "getTag") - public Optional> getTag(TagKey tagKey, Operation>> original) { - var result = original.call(tagKey); - if (result.isEmpty() && NoxesiumMod.getInstance().getConfig().printPacketExceptions) { - NoxesiumMod.getInstance().getLogger().error("Tried to fetch tag named {} from {} but it was not found", tagKey.location(), tagKey.registry()); - } - return result; - } -} diff --git a/fabric/src/main/java/com/noxcrew/noxesium/mixin/sodium/SodiumShaderLoaderMixin.java b/fabric/src/main/java/com/noxcrew/noxesium/mixin/sodium/SodiumShaderLoaderMixin.java index 734be387..d12c36ad 100644 --- a/fabric/src/main/java/com/noxcrew/noxesium/mixin/sodium/SodiumShaderLoaderMixin.java +++ b/fabric/src/main/java/com/noxcrew/noxesium/mixin/sodium/SodiumShaderLoaderMixin.java @@ -28,7 +28,7 @@ public class SodiumShaderLoaderMixin { // Determine if this shader is being provided by some resource pack, we fall back to Sodium // if anything goes wrong while doing so! var cache = NoxesiumMod.getInstance().getCachedShaders(); - var resource = cache != null ? cache.cache().get(name) : null; + var resource = cache != null ? cache.get(name) : null; if (resource != null) { try { return IOUtils.toString(resource.open(), StandardCharsets.UTF_8); diff --git a/fabric/src/main/resources/assets/noxesium/lang/en_us.json b/fabric/src/main/resources/assets/noxesium/lang/en_us.json index 46e042e6..53ec0d73 100644 --- a/fabric/src/main/resources/assets/noxesium/lang/en_us.json +++ b/fabric/src/main/resources/assets/noxesium/lang/en_us.json @@ -48,6 +48,8 @@ "noxesium.options.enum.top": "Top Corner", "noxesium.options.enum.bottom": "Bottom Corner", + "noxesium.options.enum.top_flipped": "Opposite Top Corner", + "noxesium.options.enum.bottom_flipped": "Opposite Bottom Corner", "itemGroup.noxesium.server_items": "Custom Blocks", diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 09f3f44f..303738a9 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -29,8 +29,10 @@ "custom": { "loom:injected_interfaces": { "net/minecraft/world/entity/Entity": ["com/noxcrew/noxesium/feature/entity/ExtraEntityDataHolder"], - "net/minecraft/world/entity/LivingEntity": ["com/noxcrew/noxesium/feature/entity/LivingEntityExtension"], - "net/minecraft/world/entity/Interaction": ["com/noxcrew/noxesium/feature/entity/InteractionExtension"] + "net/minecraft/world/entity/LivingEntity": ["com/noxcrew/noxesium/feature/entity/LivingEntityExtension", "com/noxcrew/noxesium/feature/entity/ArmorStandCullingExtension"], + "net/minecraft/world/entity/Interaction": ["com/noxcrew/noxesium/feature/entity/InteractionExtension"], + "net/minecraft/client/renderer/entity/state/GuardianRenderState": ["com/noxcrew/noxesium/feature/entity/BeamColorStateExtension"], + "net/minecraft/client/renderer/entity/state/EndCrystalRenderState": ["com/noxcrew/noxesium/feature/entity/BeamColorStateExtension"] } }, "mixins": [ @@ -40,15 +42,14 @@ "depends": { "fabric": "*", "fabricloader": ">=0.16.5", - "fabric-api": ">=0.105.2", - "minecraft": ">=1.21.2-pre1" + "fabric-api": ">=0.106.0", + "minecraft": ">=1.21.2-beta.5" }, "suggests": { "sodium": ">=0.6.0-beta.1", "iris": ">=1.8.0-beta.3" }, "breaks": { - "optifabric": "*", - "sodium": "<0.6.0-beta.1" + "optifabric": "*" } } diff --git a/fabric/src/main/resources/noxesium.accesswidener b/fabric/src/main/resources/noxesium.accesswidener index 382201a0..b7cd7b7d 100644 --- a/fabric/src/main/resources/noxesium.accesswidener +++ b/fabric/src/main/resources/noxesium.accesswidener @@ -8,9 +8,6 @@ accessible class net/minecraft/client/renderer/RenderType$CompositeRenderType accessible class net/minecraft/client/renderer/RenderStateShard$TextureStateShard accessible class net/minecraft/world/scores/PlayerScores -accessible method net/minecraft/client/renderer/block/model/ItemOverrides ()V -accessible method net/minecraft/client/renderer/block/model/ItemOverrides bakeModel (Lnet/minecraft/client/resources/model/ModelBaker;Lnet/minecraft/client/renderer/block/model/BlockModel;Lnet/minecraft/client/renderer/block/model/ItemOverride;)Lnet/minecraft/client/resources/model/BakedModel; - accessible method net/minecraft/client/renderer/RenderType$CompositeRenderType state ()Lnet/minecraft/client/renderer/RenderType$CompositeState; accessible field net/minecraft/client/renderer/RenderType$CompositeState textureState Lnet/minecraft/client/renderer/RenderStateShard$EmptyTextureStateShard; accessible field net/minecraft/client/renderer/RenderStateShard name Ljava/lang/String; diff --git a/fabric/src/main/resources/noxesium.mixins.json b/fabric/src/main/resources/noxesium.mixins.json index 6463dbb2..f478c0e9 100644 --- a/fabric/src/main/resources/noxesium.mixins.json +++ b/fabric/src/main/resources/noxesium.mixins.json @@ -19,8 +19,9 @@ "feature.component.ext.MinecraftExt", "feature.component.ext.SkinManagerExt", "feature.component.ext.TextureCacheExt", - "legacy.CustomItemOverridesMixin", + "legacy.ReplaceBakedModelOverrides", "legacy.culling.ArmorStandCullingMixin", + "legacy.culling.ArmorStandCullingRenderMixin", "legacy.culling.UpdateCullingOnReloadMixin", "rules.BoatCollisionMixin", "rules.CustomCreativeReloadMixin", @@ -29,9 +30,12 @@ "rules.HandItemOverrideInventoryMixin", "rules.HandItemOverrideRenderMixin", "rules.SpinAttackCollisionMixin", + "rules.entity.EndCrystalBeamRendererMixin", + "rules.entity.EndCrystalRendererMixin", "rules.entity.ExtraEntityDataMixin", "rules.entity.GuardianBeamColorRendererMixin", "rules.entity.GuardianBubblesRuleMixin", + "rules.entity.GuardianStateMixin", "rules.mouse.MouseHandlerExt", "rules.mouse.MouseLockMixin", "rules.qib.InteractionExtensionMixin", @@ -44,7 +48,6 @@ "rules.trident.TridentHandModelMixin", "rules.trident.TridentItemMixin", "settings.MapUiRenderingMixin", - "settings.MissingTagExceptionMixin", "settings.PacketDecoderMixin", "settings.PacketExceptionMixin", "settings.ResetToggleKeyMixin", @@ -75,5 +78,6 @@ "defaultRequire": 1 }, "mixins": [ + "rules.qib.JumpHookMixin" ] } diff --git a/gradle.properties b/gradle.properties index ddf35a80..5a3ca018 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,21 +2,21 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.21.2-pre1 -yarn_mappings=1.21.2-pre1+build.1 -loader_version=0.16.5 +minecraft_version=1.21.2-pre5 +yarn_mappings=1.21.2-pre5+build.2 +loader_version=0.16.7 # Fabric API -fabric_version=0.105.2+1.21.2 +fabric_version=0.106.0+1.21.2 # Mod Properties -mod_version=2.3.4-SNAPSHOT +mod_version=2.4.0-SNAPSHOT # Mod dependencies sodium = mc1.21-0.6.0-beta.1-fabric iris = 1.8.0-beta.1+1.21-fabric -modmenu = 11.0.2 +modmenu = 12.0.0-beta.1 # Enabled mods enableSodium = false enableIris = false -enableModMenu = false \ No newline at end of file +enableModMenu = true \ No newline at end of file diff --git a/paper/src/main/kotlin/com/noxcrew/noxesium/paper/api/rule/EntityRules.kt b/paper/src/main/kotlin/com/noxcrew/noxesium/paper/api/rule/EntityRules.kt index c5c4b956..67c1607a 100644 --- a/paper/src/main/kotlin/com/noxcrew/noxesium/paper/api/rule/EntityRules.kt +++ b/paper/src/main/kotlin/com/noxcrew/noxesium/paper/api/rule/EntityRules.kt @@ -15,8 +15,8 @@ public class EntityRules(private val manager: NoxesiumManager) { public val disableBubbles: RuleFunction = register(EntityRuleIndices.DISABLE_BUBBLES, 7, ::BooleanServerRule) /** - * Defines a color to use for a beam created by this entity. Applies only to guardian - * beams at this time. + * Defines a color to use for a beam created by this entity. Applies to guardian beams + * and end crystal beams. */ public val beamColor: RuleFunction> = register(EntityRuleIndices.BEAM_COLOR, 7, ::ColorServerRule) @@ -32,6 +32,11 @@ public class EntityRules(private val manager: NoxesiumManager) { */ public val interactionWidthZ: RuleFunction = register(EntityRuleIndices.QIB_WIDTH_Z, 9) { DoubleServerRule(it, 1.0) } + /** + * Defines a color used in combination with [BEAM_COLOR] to create a linear fade. + */ + public val beamFadeColor: RuleFunction> = register(EntityRuleIndices.BEAM_COLOR_FADE, 12, ::ColorServerRule) + /** Registers a new [rule]. */ private fun register(index: Int, minimumProtocol: Int, rule: (Int) -> RemoteServerRule): RuleFunction { val function = RuleFunction(index, rule)