fix: NeoForge 21.1.235 API - ModConfigSpec, EventBusSubscriber, ResourceLocation.fromNamespaceAndPath, DynamicTexture

This commit is contained in:
SashegDev
2026-08-24 03:23:12 +03:00
parent 6021a7c60b
commit 2b4cd71f3f
11 changed files with 177 additions and 160 deletions
+37 -26
View File
@@ -1,41 +1,53 @@
plugins { plugins {
id 'eclipse' id 'java-library'
id 'idea' id 'net.neoforged.gradle.userdev' version '7.1.38'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.163'
} }
version = findProperty('mod_version') ?: '1.0.0' version = mod_version
group = findProperty('group') ?: 'me.sashegdev.justasplash' group = mod_group_id
archivesBaseName = findProperty('archives_base_name') ?: 'justasplash'
base {
archivesName = mod_id
}
java.toolchain.languageVersion = JavaLanguageVersion.of(21) java.toolchain.languageVersion = JavaLanguageVersion.of(21)
println "Java: ${java.toolchain.languageVersion.get()} - NeoForge ${findProperty('neo_version')}"
minecraft {
mappings channel: findProperty('mappings_channel') ?: 'official', version: findProperty('mappings_version') ?: '1.21.1'
copyIdeResources = true
}
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { runs {
implementation "net.neoforged:neoforge:${findProperty('neo_version')}" configureEach {
implementation "javazoom:jlayer:1.0.1" systemProperty 'forge.logging.markers', 'REGISTRIES'
implementation "com.googlecode.soundlibs:mp3spi:1.9.5.4" systemProperty 'forge.logging.console.level', 'debug'
implementation "com.googlecode.soundlibs:tritonus-share:0.3.7.4" workingDirectory project.layout.projectDirectory.dir('run').dir(name)
implementation "com.googlecode.soundlibs:jorbis:0.0.17.4" modSource project.sourceSets.main
}
client {
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
} }
tasks.named('processResources', DuplicatesStrategy.INCLUDE).configure { configurations {
runtimeClasspath.extendsFrom localRuntime
}
dependencies {
implementation "net.neoforged:neoforge:${neo_version}"
implementation "javazoom:jlayer:1.0.1"
localRuntime "com.googlecode.soundlibs:mp3spi:1.9.5.4"
localRuntime "com.googlecode.soundlibs:tritonus-share:0.3.7.4"
localRuntime "com.googlecode.soundlibs:jorbis:0.0.17.4"
}
tasks.named('processResources', Copy).configure {
var replaceProperties = [ var replaceProperties = [
minecraft_version: findProperty('minecraft_version'), neo_version: findProperty('neo_version'), minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range,
loader_version: findProperty('loader_version'), mod_version: findProperty('mod_version') neo_version : neo_version, loader_version_range: loader_version_range,
mod_version : mod_version
] ]
inputs.properties(replaceProperties) inputs.properties(replaceProperties)
filesMatching(['META-INF/neoforge.mods.toml', 'pack.mcmeta']) { filesMatching(['META-INF/neoforge.mods.toml']) {
expand(replaceProperties) expand(replaceProperties)
} }
} }
@@ -47,9 +59,8 @@ jar {
'Specification-Vendor' : 'SashegDev', 'Specification-Vendor' : 'SashegDev',
'Specification-Version' : '1', 'Specification-Version' : '1',
'Implementation-Title' : project.name, 'Implementation-Title' : project.name,
'Implementation-Version' : project.jar.archiveVersion, 'Implementation-Version' : project.version,
'Implementation-Vendor' : 'SashegDev', 'Implementation-Vendor' : 'SashegDev'
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
]) ])
} }
} }
+9 -6
View File
@@ -1,10 +1,13 @@
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false org.gradle.daemon=false
minecraft_version=1.21.1 minecraft_version=1.21.1
neo_version=21.1.133 minecraft_version_range=[1.21.1]
loader_version=4.0.24 neo_version=21.1.235
mappings_channel=official loader_version_range=[1,)
mappings_version=1.21.1
mod_id=justasplash
mod_name=Just A Splash
mod_license=MIT
mod_version=1.0.0 mod_version=1.0.0
group=me.sashegdev.justasplash mod_group_id=me.sashegdev.justasplash
archives_base_name=justasplash
+3 -2
View File
@@ -1,9 +1,10 @@
pluginManagement { pluginManagement {
repositories { repositories {
gradlePluginPortal() gradlePluginPortal()
maven { url = "https://maven.neoforged.net/releases" } maven { url = 'https://maven.neoforged.net/releases' }
} }
} }
plugins { plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
} }
@@ -1,23 +1,15 @@
package me.sashegdev.justasplash; package me.sashegdev.justasplash;
import me.sashegdev.justasplash.client.Hotkey;
import me.sashegdev.justasplash.client.SplashManager;
import me.sashegdev.justasplash.client.SplashOverlay;
import me.sashegdev.justasplash.config.JustASplashConfig; import me.sashegdev.justasplash.config.JustASplashConfig;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.config.ModConfig;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
@Mod(value = "justasplash", dist = Dist.CLIENT) @Mod(value = "justasplash", dist = Dist.CLIENT)
public class JustASplash { public class JustASplash {
public JustASplash(IEventBus modBus, ModContainer container) { public JustASplash(IEventBus modBus, ModContainer container) {
container.registerConfig(ModConfig.Type.CLIENT, JustASplashConfig.SPEC); container.registerConfig(ModConfig.Type.CLIENT, JustASplashConfig.SPEC);
container.registerExtensionPoint(IConfigScreenFactory.class, (c, s) -> JustASplashConfig.createScreen(s));
Hotkey.register(modBus);
SplashOverlay.register();
SplashManager.init();
} }
} }
@@ -1,34 +1,20 @@
package me.sashegdev.justasplash.client; package me.sashegdev.justasplash.client;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.KeyMapping;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
import org.lwjgl.glfw.GLFW;
@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) @EventBusSubscriber(value = Dist.CLIENT, modid = "justasplash", bus = EventBusSubscriber.Bus.MOD)
public class Hotkey { public class Hotkey {
public static KeyMapping SPLASH = new KeyMapping("key.justasplash.splash", GLFW.GLFW_KEY_Z, "key.categories.justasplash"); public static final net.minecraft.client.KeyMapping SPLASH = new net.minecraft.client.KeyMapping(
"key.justasplash.splash",
com.mojang.blaze3d.platform.InputConstants.Type.KEYSYM,
org.lwjgl.glfw.GLFW.GLFW_KEY_Z,
"key.categories.justasplash");
public static void register(IEventBus bus) { @SubscribeEvent
bus.addListener(Hotkey::onRegister); public static void onRegister(RegisterKeyMappingsEvent e) {
}
private static void onRegister(RegisterKeyMappingsEvent e) {
e.register(SPLASH); e.register(SPLASH);
} }
@Mod.EventBusSubscriber(Dist.CLIENT)
public static class Tick {
@SubscribeEvent
public static void onTick(ClientTickEvent.Post e) {
while (SPLASH.consumeClick()) {
SplashManager.trigger();
}
}
}
} }
@@ -0,0 +1,16 @@
package me.sashegdev.justasplash.client;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent;
@EventBusSubscriber(value = Dist.CLIENT, modid = "justasplash")
public class HotkeyTick {
@SubscribeEvent
public static void onTick(ClientTickEvent.Post e) {
while (Hotkey.SPLASH.consumeClick()) {
SplashManager.trigger();
}
}
}
@@ -4,16 +4,14 @@ import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadataNode;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT)
public class ImageLoader { public class ImageLoader {
private static ResourceLocation texLoc; private static ResourceLocation texLoc;
private static int w, h; private static int w, h;
@@ -21,12 +19,11 @@ public class ImageLoader {
private static int frameIdx = 0; private static int frameIdx = 0;
private static long lastFrameMs = 0; private static long lastFrameMs = 0;
record Frame(DynamicTexture tex, int delayMs) {} record Frame(ResourceLocation loc, int delayMs) {}
public static void load(ResourceLocation loc) { public static void load(ResourceLocation loc) {
try { try {
var mc = Minecraft.getInstance(); var rm = Minecraft.getInstance().getResourceManager();
var rm = mc.getResourceManager();
var res = rm.getResource(loc).orElse(null); var res = rm.getResource(loc).orElse(null);
if (res == null) return; if (res == null) return;
try (InputStream in = res.open()) { try (InputStream in = res.open()) {
@@ -42,10 +39,9 @@ public class ImageLoader {
NativeImage img = NativeImage.read(in); NativeImage img = NativeImage.read(in);
w = img.getWidth(); w = img.getWidth();
h = img.getHeight(); h = img.getHeight();
DynamicTexture tex = new DynamicTexture(img); register(img, 0);
texLoc = new ResourceLocation("justasplash", "splash_" + System.nanoTime()); frameIdx = 0;
Minecraft.getInstance().getTextureManager().register(texLoc, tex); lastFrameMs = 0;
frames = List.of(new Frame(tex, 0));
} }
private static void loadGif(InputStream in) throws Exception { private static void loadGif(InputStream in) throws Exception {
@@ -55,50 +51,68 @@ public class ImageLoader {
List<Frame> list = new ArrayList<>(); List<Frame> list = new ArrayList<>();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
var bi = r.read(i); var bi = r.read(i);
int delay = 100; int delay = readGifDelay(r, i);
try { var img = toNativeImage(bi);
var meta = r.getImageMetadata(i);
var tree = meta.getAsTree("javax_imageio_gif_image_1.0");
var gce = tree.getChildNodes();
for (int j = 0; j < gce.getLength(); j++) {
var node = gce.item(j);
if ("GraphicControlExtension".equals(node.getNodeName())) {
delay = Integer.parseInt(node.getAttributes().getNamedItem("delayTime").getNodeValue()) * 10;
}
}
} catch (Exception ignored) {}
NativeImage img = toNativeImage(bi);
w = img.getWidth(); w = img.getWidth();
h = img.getHeight(); h = img.getHeight();
DynamicTexture tex = new DynamicTexture(img); list.add(new Frame(registerImg(img), delay <= 0 ? 100 : delay));
ResourceLocation loc = new ResourceLocation("justasplash", "splash_gif_" + i + "_" + System.nanoTime());
Minecraft.getInstance().getTextureManager().register(loc, tex);
list.add(new Frame(tex, delay == 0 ? 100 : delay));
} }
if (!list.isEmpty()) { if (!list.isEmpty()) {
frames = list; frames = list;
texLoc = frames.get(0).tex.getTextureLocation(); texLoc = list.get(0).loc();
frameIdx = 0;
lastFrameMs = 0;
} }
} }
private static int readGifDelay(ImageReader r, int idx) {
try {
IIOMetadataNode tree = (IIOMetadataNode) r.getImageMetadata(idx).getAsTree("javax_imageio_gif_image_1.0");
var nodes = tree.getElementsByTagName("GraphicControlExtension");
for (int j = 0; j < nodes.getLength(); j++) {
return Integer.parseInt(nodes.item(j).getAttributes().getNamedItem("delayTime").getNodeValue()) * 10;
}
} catch (Exception ignored) {}
return 100;
}
private static ResourceLocation registerImg(NativeImage img) {
ResourceLocation loc = ResourceLocation.fromNamespaceAndPath("justasplash", "dynamic/splash_" + System.nanoTime());
Minecraft.getInstance().getTextureManager().register(loc, new DynamicTexture(img));
return loc;
}
private static void register(NativeImage img, int idx) {
texLoc = registerImg(img);
frames = List.of(new Frame(texLoc, 0));
}
private static NativeImage toNativeImage(java.awt.image.BufferedImage bi) { private static NativeImage toNativeImage(java.awt.image.BufferedImage bi) {
int wi = bi.getWidth(), hi = bi.getHeight(); int wi = bi.getWidth(), hi = bi.getHeight();
NativeImage img = new NativeImage(wi, hi, false); NativeImage img = new NativeImage(wi, hi, false);
for (int y = 0; y < hi; y++) for (int x = 0; x < wi; x++) { for (int y = 0; y < hi; y++) {
for (int x = 0; x < wi; x++) {
int argb = bi.getRGB(x, y); int argb = bi.getRGB(x, y);
img.setPixelRGBA(x, y, argb); int a = (argb >>> 24) & 0xFF;
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = argb & 0xFF;
img.setPixelRGBA(x, y, (a << 24) | (b << 16) | (g << 8) | r);
}
} }
return img; return img;
} }
public static ResourceLocation getTexture() { public static ResourceLocation getTexture() {
if (frames.size() <= 1) return texLoc; if (frames.isEmpty()) return null;
if (frames.size() > 1) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
int delay = frames.get(frameIdx).delayMs; int delay = frames.get(frameIdx).delayMs();
if (now - lastFrameMs > delay) { if (now - lastFrameMs > delay) {
frameIdx = (frameIdx + 1) % frames.size(); frameIdx = (frameIdx + 1) % frames.size();
lastFrameMs = now; lastFrameMs = now;
texLoc = frames.get(frameIdx).tex.getTextureLocation(); texLoc = frames.get(frameIdx).loc();
}
} }
return texLoc; return texLoc;
} }
@@ -1,48 +1,15 @@
package me.sashegdev.justasplash.client; package me.sashegdev.justasplash.client;
import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.resources.ResourceLocation;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.LayeredDraw;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent; import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
@EventBusSubscriber(value = Dist.CLIENT, modid = "justasplash", bus = EventBusSubscriber.Bus.MOD)
public class SplashOverlay { public class SplashOverlay {
public static void register() {
}
@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public static class Reg {
@SubscribeEvent @SubscribeEvent
public static void onLayers(RegisterGuiLayersEvent e) { public static void onLayers(RegisterGuiLayersEvent e) {
e.registerAboveAll(new net.minecraft.resources.ResourceLocation("justasplash", "splash"), SplashOverlay::render); e.registerAboveAll(ResourceLocation.fromNamespaceAndPath("justasplash", "splash"), (guiGraphics, deltaTracker) -> SplashRenderer.render(guiGraphics));
}
}
private static void render(GuiGraphics g, DeltaTracker d) {
if (!SplashManager.isShowing()) return;
var mc = Minecraft.getInstance();
int w = mc.getWindow().getGuiScaledWidth();
int h = mc.getWindow().getGuiScaledHeight();
float a = SplashManager.getFadeAlpha();
if (a <= 0.01f) return;
RenderSystem.enableBlend();
RenderSystem.setShaderColor(1, 1, 1, a);
var tex = ImageLoader.getTexture();
if (tex != null) {
int iw = ImageLoader.getWidth();
int ih = ImageLoader.getHeight();
float scale = Math.min((float) w / iw, (float) h / ih);
int dw = (int) (iw * scale);
int dh = (int) (ih * scale);
int x = (w - dw) / 2;
int y = (h - dh) / 2;
g.blit(tex, x, y, 0, 0, dw, dh, dw, dh);
}
RenderSystem.setShaderColor(1, 1, 1, 1);
RenderSystem.disableBlend();
} }
} }
@@ -0,0 +1,33 @@
package me.sashegdev.justasplash.client;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
public class SplashRenderer {
public static void render(GuiGraphics g) {
if (!SplashManager.isShowing()) return;
var mc = Minecraft.getInstance();
int w = mc.getWindow().getGuiScaledWidth();
int h = mc.getWindow().getGuiScaledHeight();
float a = SplashManager.getFadeAlpha();
if (a <= 0.01f) return;
RenderSystem.enableBlend();
RenderSystem.setShaderColor(1f, 1f, 1f, a);
ResourceLocation tex = ImageLoader.getTexture();
if (tex != null && ImageLoader.getWidth() > 0) {
int iw = ImageLoader.getWidth();
int ih = ImageLoader.getHeight();
float scale = Math.max((float) w / iw, (float) h / ih);
int dw = (int) (iw * scale);
int dh = (int) (ih * scale);
int x = (w - dw) / 2;
int y = (h - dh) / 2;
g.blit(tex, x, y, 0, 0, dw, dh, dw, dh);
}
RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
RenderSystem.disableBlend();
}
}
@@ -1,20 +1,18 @@
package me.sashegdev.justasplash.config; package me.sashegdev.justasplash.config;
import net.minecraft.client.gui.screens.Screen; import net.neoforged.neoforge.common.ModConfigSpec;
import net.neoforged.common.ModConfigSpec;
import net.neoforged.neoforge.common.ModConfigSpec.*;
public class JustASplashConfig { public class JustASplashConfig {
public static final ModConfigSpec SPEC; public static final ModConfigSpec SPEC;
public static final ConfigValue<String> SPLASH_IMAGE; public static final ModConfigSpec.ConfigValue<String> SPLASH_IMAGE;
public static final ConfigValue<String> SPLASH_SOUND; public static final ModConfigSpec.ConfigValue<String> SPLASH_SOUND;
public static final DoubleValue FADE; public static final ModConfigSpec.DoubleValue FADE;
public static final DoubleValue VOLUME; public static final ModConfigSpec.DoubleValue VOLUME;
static { static {
Builder b = new Builder(); ModConfigSpec.Builder b = new ModConfigSpec.Builder();
b.push("splash"); b.push("splash");
SPLASH_IMAGE = b.comment("ResourceLocation png|gif in assets/justasplash/ or config/justasplash/ - e.g. justasplash:textures/gui/splashes/splash.png") SPLASH_IMAGE = b.comment("ResourceLocation png|gif in assets/justasplash/ - e.g. justasplash:textures/gui/splashes/splash.png")
.define("splashImage", "justasplash:textures/gui/splashes/splash.png"); .define("splashImage", "justasplash:textures/gui/splashes/splash.png");
SPLASH_SOUND = b.comment("ResourceLocation ogg|mp3 - e.g. justasplash:sounds/splash.ogg, empty to disable") SPLASH_SOUND = b.comment("ResourceLocation ogg|mp3 - e.g. justasplash:sounds/splash.ogg, empty to disable")
.define("splashSound", "justasplash:sounds/splash.ogg"); .define("splashSound", "justasplash:sounds/splash.ogg");
@@ -25,8 +23,4 @@ public class JustASplashConfig {
b.pop(); b.pop();
SPEC = b.build(); SPEC = b.build();
} }
public static Screen createScreen(Screen parent) {
return new net.neoforged.neoforge.client.gui.ConfigurationScreen(parent, SPEC, "justasplash");
}
} }
@@ -1,25 +1,25 @@
modLoader="javafml" modLoader="javafml"
loaderVersion="[4,)" loaderVersion="${loader_version_range}"
license="MIT" license="MIT"
issueTrackerURL="https://git.swe.zern.cc/sasheg/justasplash-neo/issues" issueTrackerURL="https://git.swe.zern.cc/sasheg/justasplash-neo/issues"
[[mods]] [[mods]]
modId="justasplash" modId="justasplash"
version="${mod_version}" version="${mod_version}"
displayName="Just A Splash" displayName="Just A Splash"
updateJSONURL="https://git.swe.zern.cc/sasheg/justasplash-neo"
displayURL="https://git.swe.zern.cc/sasheg/justasplash-neo" displayURL="https://git.swe.zern.cc/sasheg/justasplash-neo"
logoFile="justasplash.png"
authors="SashegDev" authors="SashegDev"
description="Hotkey Z -> fullscreen png/gif + ogg/mp3 splash, 100% -> 0% fade, client only. Fully configurable." description="Hotkey Z -> fullscreen png/gif + ogg/mp3 splash, 100% -> 0% fade, client only. Fully configurable."
[[dependencies.justasplash]] [[dependencies.justasplash]]
modId="neoforge" modId="neoforge"
type="required" type="required"
versionRange="[21.1.133,21.2)" versionRange="[21.1.0,)"
ordering="NONE" ordering="NONE"
side="CLIENT" side="CLIENT"
[[dependencies.justasplash]] [[dependencies.justasplash]]
modId="minecraft" modId="minecraft"
type="required" type="required"
versionRange="[1.21.1,1.22)" versionRange="${minecraft_version_range}"
ordering="NONE" ordering="NONE"
side="CLIENT" side="CLIENT"