From 72ed429af9c1e1ff51d5fc91f308e958a6889937 Mon Sep 17 00:00:00 2001 From: Notenoughmail <78008321+Notenoughmail@users.noreply.github.com> Date: Sat, 18 May 2024 22:05:29 -0700 Subject: [PATCH 1/5] "Functional" Particles - Add particle provider registry event - Add asset generator for particle jsons (just a list of textures) - Add KubeAnimatedParticle, a custom Particle class that exposes things to scriptors - Add particle asset auto-gen to particle type builder (currently broken for reasons...) --- .../kubejs/bindings/event/ClientEvents.java | 2 + .../client/GenerateClientAssetsEventJS.java | 4 + .../kubejs/client/KubeAnimatedParticle.java | 101 ++++++++++++++++++ .../client/KubeJSClientEventHandler.java | 6 ++ .../mods/kubejs/client/ParticleGenerator.java | 31 ++++++ .../ParticleProviderRegistryEventJS.java | 37 +++++++ .../mods/kubejs/core/MinecraftClientKJS.java | 12 +++ .../kubejs/generator/AssetJsonGenerator.java | 6 ++ .../mods/kubejs/misc/ParticleTypeBuilder.java | 17 +++ 9 files changed, 216 insertions(+) create mode 100644 common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java create mode 100644 common/src/main/java/dev/latvian/mods/kubejs/client/ParticleGenerator.java create mode 100644 common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java diff --git a/common/src/main/java/dev/latvian/mods/kubejs/bindings/event/ClientEvents.java b/common/src/main/java/dev/latvian/mods/kubejs/bindings/event/ClientEvents.java index 64054a999..28a9b90b3 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/bindings/event/ClientEvents.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/bindings/event/ClientEvents.java @@ -6,6 +6,7 @@ import dev.latvian.mods.kubejs.client.DebugInfoEventJS; import dev.latvian.mods.kubejs.client.GenerateClientAssetsEventJS; import dev.latvian.mods.kubejs.client.LangEventJS; +import dev.latvian.mods.kubejs.client.ParticleProviderRegistryEventJS; import dev.latvian.mods.kubejs.client.painter.screen.PaintScreenEventJS; import dev.latvian.mods.kubejs.event.EventGroup; import dev.latvian.mods.kubejs.event.EventHandler; @@ -25,4 +26,5 @@ public interface ClientEvents { EventHandler PAINT_SCREEN = GROUP.client("paintScreen", () -> PaintScreenEventJS.class); EventHandler ATLAS_SPRITE_REGISTRY = GROUP.client("atlasSpriteRegistry", () -> AtlasSpriteRegistryEventJS.class).extra(Extra.REQUIRES_ID); EventHandler LANG = GROUP.client("lang", () -> LangEventJS.class).extra(Extra.REQUIRES_STRING); + EventHandler PARTICLE_PROVIDER_REGISTRY = GROUP.client("particleProviderRegistry", () -> ParticleProviderRegistryEventJS.class); } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java b/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java index 9361393e5..d6a29b9bc 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java @@ -58,4 +58,8 @@ public void defaultHandheldItemModel(ResourceLocation id) { model.texture("layer0", id.getNamespace() + ":item/" + id.getPath()); }); } + + public void particle(ResourceLocation id, Consumer consumer) { + generator.particle(id, consumer); + } } \ No newline at end of file diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java new file mode 100644 index 000000000..1a9c17858 --- /dev/null +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java @@ -0,0 +1,101 @@ +package dev.latvian.mods.kubejs.client; + +import dev.latvian.mods.kubejs.typings.Info; +import dev.latvian.mods.rhino.mod.util.color.Color; +import it.unimi.dsi.fastutil.floats.Float2IntFunction; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.RandomSource; + +public class KubeAnimatedParticle extends SimpleAnimatedParticle { + + private Float2IntFunction lightColorFunction; + + public KubeAnimatedParticle(ClientLevel clientLevel, SpriteSet spriteSet, double x, double y, double z) { + super(clientLevel, x, y, z, spriteSet, 0.0125F); + setLifetime(20); + setSpriteFromAge(spriteSet); + lightColorFunction = super::getLightColor; + } + + public void setGravity(float g) { + this.gravity = g; + } + + @Info(value = "Sets the friction value of the particle, the particle's motion is multiplied by this value every tick") + public void setFriction(float f) { + this.friction = f; + } + + public void setColor(Color color, boolean alpha) { + setColor(color.getRgbJS()); + if (alpha) { + // setAlpha(color.getArgbJS()); TODO: Eugh bitwise math + } + } + + public void setColor(Color color) { + setColor(color, false); + } + + public void setPhysicality(boolean hasPhysics) { + this.hasPhysics = hasPhysics; + } + + public void setFasterWhenYMotionBlocked(boolean b) { + speedUpWhenYMotionIsBlocked = b; + } + + public void setLightColor(Float2IntFunction function) { + lightColorFunction = function; + } + + // Getters for protected values + + public ClientLevel getLevel() { + return level; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + public double getXSpeed() { + return xd; + } + + public double getYSpeed() { + return yd; + } + + public double getZSpeed() { + return zd; + } + + public SpriteSet getSpriteSet() { + return sprites; + } + + public TextureAtlasSprite getSprite() { + return sprite; + } + + public RandomSource getRandom() { + return random; + } + + @Override + public int getLightColor(float f) { + return lightColorFunction.get(f); + } +} diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java index 7376e82af..b2ff91297 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java @@ -2,6 +2,7 @@ import dev.architectury.event.EventResult; import dev.architectury.event.events.client.ClientGuiEvent; +import dev.architectury.event.events.client.ClientLifecycleEvent; import dev.architectury.event.events.client.ClientPlayerEvent; import dev.architectury.event.events.client.ClientTooltipEvent; import dev.architectury.hooks.client.screen.ScreenAccess; @@ -57,6 +58,7 @@ public void init() { ClientGuiEvent.RENDER_POST.register(Painter.INSTANCE::guiScreenDraw); ClientGuiEvent.INIT_PRE.register(this::guiPreInit); ClientGuiEvent.INIT_POST.register(this::guiPostInit); + ClientLifecycleEvent.CLIENT_SETUP.register(this::clientSetup); //ClientTextureStitchEvent.POST.register(this::postAtlasStitch); } @@ -170,6 +172,10 @@ private void guiPostInit(Screen screen, ScreenAccess access) { } } + private void clientSetup(Minecraft mc) { + ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryEventJS()); + } + /*private void postAtlasStitch(TextureAtlas atlas) { if (!ClientProperties.get().getExportAtlases()) { return; diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleGenerator.java b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleGenerator.java new file mode 100644 index 000000000..d63999a5a --- /dev/null +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleGenerator.java @@ -0,0 +1,31 @@ +package dev.latvian.mods.kubejs.client; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import net.minecraft.resources.ResourceLocation; + +import java.util.ArrayList; +import java.util.List; + +public class ParticleGenerator { + + public transient List textures = new ArrayList<>(); + + public ParticleGenerator texture(ResourceLocation location) { + textures.add(location.toString()); + return this; + } + + public ParticleGenerator textures(List textures) { + this.textures = textures; + return this; + } + + public JsonObject toJson() { + final JsonObject json = new JsonObject(); + final JsonArray textures = new JsonArray(this.textures.size()); + this.textures.forEach(textures::add); + json.add("textures", textures); + return json; + } +} diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java new file mode 100644 index 000000000..7554507e0 --- /dev/null +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java @@ -0,0 +1,37 @@ +package dev.latvian.mods.kubejs.client; + +import dev.architectury.registry.client.particle.ParticleProviderRegistry; +import dev.latvian.mods.kubejs.event.EventJS; +import net.minecraft.Util; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; + +import java.util.function.Consumer; + +public class ParticleProviderRegistryEventJS extends EventJS { + + public void register(ParticleType type, ParticleProvider provider) { + ParticleProviderRegistry.register(type, provider); + } + + public void registerSimple(ParticleType type, Consumer particle) { + ParticleProviderRegistry.register(type, set -> (t, level, x, y, z, dx, dy, dz) -> Util.make(new KubeAnimatedParticle(level, set, x, y, z), particle)); + } + + public void registerSimple(ParticleType type) { + registerSimple(type, particle -> {}); + } + + @FunctionalInterface + public interface ParticleProvider extends ParticleProviderRegistry.DeferredParticleProvider { + Particle create(T particleOptions, ClientLevel level, ParticleProviderRegistry.ExtendedSpriteSet spriteSet, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed); + + @Override + default net.minecraft.client.particle.ParticleProvider create(ParticleProviderRegistry.ExtendedSpriteSet spriteSet) { + return (t, level, x, y, z, xSpeed, ySpeed, zSpeed) -> create(t, level, spriteSet, x, y, z, xSpeed, ySpeed, zSpeed); + } + } +} diff --git a/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java b/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java index 2d31f0769..5df5a4de5 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.InputConstants; import dev.latvian.mods.kubejs.bindings.event.ItemEvents; import dev.latvian.mods.kubejs.client.ClientProperties; +import dev.latvian.mods.kubejs.client.KubeAnimatedParticle; import dev.latvian.mods.kubejs.item.ItemClickedEventJS; import dev.latvian.mods.kubejs.net.FirstClickMessage; import dev.latvian.mods.kubejs.script.ScriptType; @@ -11,6 +12,8 @@ import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.SpriteSet; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import org.jetbrains.annotations.Nullable; @@ -84,6 +87,15 @@ public interface MinecraftClientKJS extends MinecraftEnvironmentKJS { return Screen.hasAltDown(); } + // TODO: A different name may be better, or perhaps this should be in ClientLevelKJS + default KubeAnimatedParticle kjs$customParticle(SpriteSet spriteSet, double x, double y, double z) { + return kjs$customParticle(kjs$self().level, spriteSet, x, y, z); + } + + default KubeAnimatedParticle kjs$customParticle(ClientLevel level, SpriteSet spriteSet, double x, double y, double z) { + return new KubeAnimatedParticle(level, spriteSet, x, y, z); + } + @HideFromJS default void kjs$startAttack0() { if (ItemEvents.FIRST_LEFT_CLICKED.hasListeners()) { diff --git a/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java b/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java index 562648590..8cc3b6d6c 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java @@ -4,6 +4,7 @@ import dev.latvian.mods.kubejs.KubeJSPaths; import dev.latvian.mods.kubejs.client.ModelGenerator; import dev.latvian.mods.kubejs.client.MultipartBlockStateGenerator; +import dev.latvian.mods.kubejs.client.ParticleGenerator; import dev.latvian.mods.kubejs.client.StencilTexture; import dev.latvian.mods.kubejs.client.VariantBlockStateGenerator; import dev.latvian.mods.kubejs.script.data.GeneratedData; @@ -47,6 +48,11 @@ public void itemModel(ResourceLocation id, Consumer consumer) { json(asItemModelLocation(id), gen.toJson()); } + public void particle(ResourceLocation id, Consumer consumer) { + var gen = Util.make(new ParticleGenerator(), consumer); + json(new ResourceLocation(id.getNamespace(), "particles/" + id.getPath()), gen.toJson()); + } + public static ResourceLocation asItemModelLocation(ResourceLocation id) { return new ResourceLocation(id.getNamespace(), "models/item/" + id.getPath()); } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java b/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java index e257ccf48..23b2bceb6 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java @@ -1,18 +1,24 @@ package dev.latvian.mods.kubejs.misc; +import dev.latvian.mods.kubejs.client.ParticleGenerator; +import dev.latvian.mods.kubejs.generator.AssetJsonGenerator; import dev.latvian.mods.kubejs.registry.BuilderBase; import dev.latvian.mods.kubejs.registry.RegistryInfo; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.resources.ResourceLocation; +import java.util.function.Consumer; + public class ParticleTypeBuilder extends BuilderBase> { public transient boolean overrideLimiter; public transient ParticleOptions.Deserializer deserializer; + public transient Consumer assetGen; public ParticleTypeBuilder(ResourceLocation i) { super(i); overrideLimiter = false; + assetGen = g -> g.texture(id); } @Override @@ -34,9 +40,20 @@ public ParticleTypeBuilder overrideLimiter(boolean o) { return this; } + public ParticleTypeBuilder textures(Consumer gen) { + assetGen = gen; + return this; + } + // TODO: Figure out if this is even needed public ParticleTypeBuilder deserializer(ParticleOptions.Deserializer d) { deserializer = d; return this; } + + // TODO: For some reason this does NOT work on first resource load without the breakpoints in ParticleEngine + @Override + public void generateAssetJsons(AssetJsonGenerator generator) { + generator.particle(id, assetGen); + } } From 153d6944e1b72eaecd10dccd24b9ac7d71274567 Mon Sep 17 00:00:00 2001 From: Notenoughmail <78008321+Notenoughmail@users.noreply.github.com> Date: Sun, 19 May 2024 14:17:27 -0700 Subject: [PATCH 2/5] No Good Deed Goes Unpunished - Fix particle provider registration firing too late --- .../client/KubeJSClientEventHandler.java | 5 ----- .../core/mixin/common/ParticleEngineMixin.java | 18 ++++++++++++++++++ .../mods/kubejs/misc/ParticleTypeBuilder.java | 1 - .../main/resources/kubejs-common.mixins.json | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java index b2ff91297..cd8759bda 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java @@ -58,7 +58,6 @@ public void init() { ClientGuiEvent.RENDER_POST.register(Painter.INSTANCE::guiScreenDraw); ClientGuiEvent.INIT_PRE.register(this::guiPreInit); ClientGuiEvent.INIT_POST.register(this::guiPostInit); - ClientLifecycleEvent.CLIENT_SETUP.register(this::clientSetup); //ClientTextureStitchEvent.POST.register(this::postAtlasStitch); } @@ -172,10 +171,6 @@ private void guiPostInit(Screen screen, ScreenAccess access) { } } - private void clientSetup(Minecraft mc) { - ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryEventJS()); - } - /*private void postAtlasStitch(TextureAtlas atlas) { if (!ClientProperties.get().getExportAtlases()) { return; diff --git a/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java b/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java new file mode 100644 index 000000000..21a4bdff3 --- /dev/null +++ b/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java @@ -0,0 +1,18 @@ +package dev.latvian.mods.kubejs.core.mixin.common; + +import dev.latvian.mods.kubejs.bindings.event.ClientEvents; +import dev.latvian.mods.kubejs.client.ParticleProviderRegistryEventJS; +import net.minecraft.client.particle.ParticleEngine; +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; + +@Mixin(ParticleEngine.class) +public abstract class ParticleEngineMixin { + + @Inject(method = "registerProviders", at = @At("RETURN")) + private void registerParticleProvidersKJS(CallbackInfo ci) { + ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryEventJS()); + } +} diff --git a/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java b/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java index 23b2bceb6..147e40e70 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/misc/ParticleTypeBuilder.java @@ -51,7 +51,6 @@ public ParticleTypeBuilder deserializer(ParticleOptions.Deserializer d) { return this; } - // TODO: For some reason this does NOT work on first resource load without the breakpoints in ParticleEngine @Override public void generateAssetJsons(AssetJsonGenerator generator) { generator.particle(id, assetGen); diff --git a/common/src/main/resources/kubejs-common.mixins.json b/common/src/main/resources/kubejs-common.mixins.json index 176a78b95..ee64c5076 100644 --- a/common/src/main/resources/kubejs-common.mixins.json +++ b/common/src/main/resources/kubejs-common.mixins.json @@ -55,6 +55,7 @@ "LocalPlayerMixin", "MinecraftClientMixin", "OptionsMixin", + "ParticleEngineMixin", "ScreenMixin", "WindowMixin", "WorldOpenFlowsMixin", From cda4fb7923be8737d8aa9f191ed2c4804b7f03b9 Mon Sep 17 00:00:00 2001 From: Notenoughmail <78008321+Notenoughmail@users.noreply.github.com> Date: Sun, 19 May 2024 15:31:43 -0700 Subject: [PATCH 3/5] Sounds - Add sound event asset generation --- .../client/GenerateClientAssetsEventJS.java | 4 + .../client/GeneratedClientResourcePack.java | 2 + .../kubejs/client/KubeAnimatedParticle.java | 2 +- .../mods/kubejs/client/SoundGenerator.java | 157 ++++++++++++++++++ .../mods/kubejs/core/MinecraftClientKJS.java | 2 +- .../kubejs/generator/AssetJsonGenerator.java | 15 ++ .../mods/kubejs/misc/SoundEventBuilder.java | 18 ++ 7 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java b/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java index d6a29b9bc..96a44af50 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/GenerateClientAssetsEventJS.java @@ -62,4 +62,8 @@ public void defaultHandheldItemModel(ResourceLocation id) { public void particle(ResourceLocation id, Consumer consumer) { generator.particle(id, consumer); } + + public void sounds(String namespace, Consumer consumer) { + generator.sounds(namespace, consumer); + } } \ No newline at end of file diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/GeneratedClientResourcePack.java b/common/src/main/java/dev/latvian/mods/kubejs/client/GeneratedClientResourcePack.java index 0458536ab..9a56793ae 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/GeneratedClientResourcePack.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/GeneratedClientResourcePack.java @@ -97,6 +97,8 @@ public void generate(Map map) { ClientEvents.HIGH_ASSETS.post(ScriptType.CLIENT, new GenerateClientAssetsEventJS(generator)); + generator.buildSounds(); + for (var lang : ClientEvents.LANG.findUniqueExtraIds(ScriptType.CLIENT)) { var l = String.valueOf(lang); diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java index 1a9c17858..56abeb4cf 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java @@ -32,7 +32,7 @@ public void setFriction(float f) { public void setColor(Color color, boolean alpha) { setColor(color.getRgbJS()); if (alpha) { - // setAlpha(color.getArgbJS()); TODO: Eugh bitwise math + setAlpha((color.getArgbJS() >> 24) / 255.0F); } } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java b/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java new file mode 100644 index 000000000..1c8d44e2e --- /dev/null +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java @@ -0,0 +1,157 @@ +package dev.latvian.mods.kubejs.client; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import net.minecraft.Util; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public class SoundGenerator { + + private final Map entries = new HashMap<>(); + + public void addSound(String path, Consumer consumer) { + if (entries.containsKey(path)) { + consumer.accept(entries.get(path)); + } else { + entries.put(path, Util.make(new SoundEntry(), consumer)); + } + } + + public JsonObject toJson() { + final JsonObject json = new JsonObject(); + entries.forEach((path, entry) -> json.add(path, entry.toJson())); + return json; + } + + public static class SoundEntry { + + private boolean replace = false; + @Nullable + private String subtitle; + private final List sounds = new ArrayList<>(); + + public SoundEntry replace(boolean b) { + replace = b; + return this; + } + + public SoundEntry subtitle(String subtitle) { + this.subtitle = subtitle; + return this; + } + + public SoundEntry sounds(ResourceLocation... sounds) { + this.sounds.addAll(Stream.of(sounds).map(SoundInstance::new).toList()); + return this; + } + + public SoundEntry sound(ResourceLocation file, Consumer consumer) { + sounds.add(Util.make(new SoundInstance(file), consumer)); + return this; + } + + public JsonObject toJson() { + final JsonObject json = new JsonObject(); + if (replace) { + json.addProperty("replace", true); + } + if (subtitle != null) { + json.addProperty("subtitle", subtitle); + } + if (!sounds.isEmpty()) { + final JsonArray array = new JsonArray(sounds.size()); + sounds.forEach(instance -> array.add(instance.toJson())); + json.add("sounds" ,array); + } + return json; + } + } + + public static class SoundInstance { + + private final ResourceLocation fileLocation; + private boolean complex = false; + private float volume = 1.0F; + private float pitch = 1.0F; + private int weight = 1; + private boolean stream = false; + private int attenuationDistance = 16; + private boolean preload = false; + private boolean isEventReference = false; + + + public SoundInstance(ResourceLocation fileLocation) { + this.fileLocation = fileLocation; + } + + private SoundInstance complex() { + complex = true; + return this; + } + + public SoundInstance volume(float f) { + volume = Mth.clamp(f, 0.0F, 1.0F); + return complex(); + } + + public SoundInstance pitch(float f) { + pitch = Mth.clamp(f, 0.0F, 1.0F); + return complex(); + } + + public SoundInstance weight(int i) { + weight = i; + return complex(); + } + + public SoundInstance stream(boolean b) { + stream = b; + return complex(); + } + + public SoundInstance attenuationDistance(int i) { + attenuationDistance = i; + return complex(); + } + + public SoundInstance preload(boolean b) { + preload = b; + return complex(); + } + + public SoundInstance asReferenceToEvent() { + isEventReference = true; + return complex(); + } + + public JsonElement toJson() { + if (!complex) { + return new JsonPrimitive(fileLocation.toString()); + } + + final JsonObject json = new JsonObject(); + json.addProperty("name", fileLocation.toString()); + json.addProperty("volume", volume); + json.addProperty("pitch", pitch); + json.addProperty("weight", weight); + json.addProperty("stream", stream); + json.addProperty("attenuation_distance", attenuationDistance); + json.addProperty("preload", preload); + if (isEventReference) { + json.addProperty("type", "event"); + } + return json; + } + } +} diff --git a/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java b/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java index 5df5a4de5..2d9737864 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/core/MinecraftClientKJS.java @@ -87,7 +87,7 @@ public interface MinecraftClientKJS extends MinecraftEnvironmentKJS { return Screen.hasAltDown(); } - // TODO: A different name may be better, or perhaps this should be in ClientLevelKJS + // PR Review: A different name may be better, or perhaps this should be in ClientLevelKJS default KubeAnimatedParticle kjs$customParticle(SpriteSet spriteSet, double x, double y, double z) { return kjs$customParticle(kjs$self().level, spriteSet, x, y, z); } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java b/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java index 8cc3b6d6c..7384d7898 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/generator/AssetJsonGenerator.java @@ -5,6 +5,7 @@ import dev.latvian.mods.kubejs.client.ModelGenerator; import dev.latvian.mods.kubejs.client.MultipartBlockStateGenerator; import dev.latvian.mods.kubejs.client.ParticleGenerator; +import dev.latvian.mods.kubejs.client.SoundGenerator; import dev.latvian.mods.kubejs.client.StencilTexture; import dev.latvian.mods.kubejs.client.VariantBlockStateGenerator; import dev.latvian.mods.kubejs.script.data.GeneratedData; @@ -22,10 +23,12 @@ public class AssetJsonGenerator extends ResourceGenerator { private final Map stencils; + private final Map sounds; public AssetJsonGenerator(Map m) { super(ConsoleJS.CLIENT, m); this.stencils = new HashMap<>(); + this.sounds = new HashMap<>(); } public void blockState(ResourceLocation id, Consumer consumer) { @@ -53,6 +56,14 @@ public void particle(ResourceLocation id, Consumer consumer) json(new ResourceLocation(id.getNamespace(), "particles/" + id.getPath()), gen.toJson()); } + public void sounds(String mod, Consumer consumer) { + if (sounds.containsKey(mod)) { + consumer.accept(sounds.get(mod)); + } else { + sounds.put(mod, Util.make(new SoundGenerator(), consumer)); + } + } + public static ResourceLocation asItemModelLocation(ResourceLocation id) { return new ResourceLocation(id.getNamespace(), "models/item/" + id.getPath()); } @@ -87,4 +98,8 @@ public void stencil(ResourceLocation target, String stencil, JsonObject colors) add(new ResourceLocation(target.getNamespace(), "textures/" + target.getPath() + ".png.mcmeta"), () -> st1.mcmeta, false); } } + + public void buildSounds() { + sounds.forEach((mod, gen) -> json(new ResourceLocation(mod, "sounds"), gen.toJson())); + } } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/misc/SoundEventBuilder.java b/common/src/main/java/dev/latvian/mods/kubejs/misc/SoundEventBuilder.java index c470c7fc8..02b4f38a2 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/misc/SoundEventBuilder.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/misc/SoundEventBuilder.java @@ -1,13 +1,26 @@ package dev.latvian.mods.kubejs.misc; +import dev.latvian.mods.kubejs.client.SoundGenerator; +import dev.latvian.mods.kubejs.generator.AssetJsonGenerator; import dev.latvian.mods.kubejs.registry.BuilderBase; import dev.latvian.mods.kubejs.registry.RegistryInfo; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; +import java.util.function.Consumer; + public class SoundEventBuilder extends BuilderBase { + + public transient Consumer gen; + public SoundEventBuilder(ResourceLocation i) { super(i); + gen = e -> e.sounds(id); + } + + public SoundEventBuilder sound(Consumer consumer) { + gen = consumer; + return this; } @Override @@ -19,4 +32,9 @@ public final RegistryInfo getRegistryType() { public SoundEvent createObject() { return SoundEvent.createVariableRangeEvent(id); } + + @Override + public void generateAssetJsons(AssetJsonGenerator generator) { + generator.sounds(id.getNamespace(), g -> g.addSound(id.getPath(), gen)); + } } From 5a56c380d717451fabfe73ad328a60fc49d7afc6 Mon Sep 17 00:00:00 2001 From: Notenoughmail <78008321+Notenoughmail@users.noreply.github.com> Date: Sun, 19 May 2024 16:56:33 -0700 Subject: [PATCH 4/5] Cleanup - Address ChiefArug's comments --- .../client/KubeJSClientEventHandler.java | 5 +++++ .../mods/kubejs/client/SoundGenerator.java | 6 ++++++ .../core/mixin/common/ParticleEngineMixin.java | 18 ------------------ .../main/resources/kubejs-common.mixins.json | 1 - 4 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java index cd8759bda..c02b9470c 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java @@ -58,6 +58,7 @@ public void init() { ClientGuiEvent.RENDER_POST.register(Painter.INSTANCE::guiScreenDraw); ClientGuiEvent.INIT_PRE.register(this::guiPreInit); ClientGuiEvent.INIT_POST.register(this::guiPostInit); + ClientLifecycleEvent.CLIENT_STARTED.register(this::clientStart); //ClientTextureStitchEvent.POST.register(this::postAtlasStitch); } @@ -171,6 +172,10 @@ private void guiPostInit(Screen screen, ScreenAccess access) { } } + private void clientStart(Minecraft mc) { + ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryEventJS()); + } + /*private void postAtlasStitch(TextureAtlas atlas) { if (!ClientProperties.get().getExportAtlases()) { return; diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java b/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java index 1c8d44e2e..510b35c9e 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/SoundGenerator.java @@ -46,6 +46,8 @@ public SoundEntry replace(boolean b) { return this; } + public SoundEntry replace() { return replace(true); } + public SoundEntry subtitle(String subtitle) { this.subtitle = subtitle; return this; @@ -120,6 +122,8 @@ public SoundInstance stream(boolean b) { return complex(); } + public SoundInstance stream() { return stream(true); } + public SoundInstance attenuationDistance(int i) { attenuationDistance = i; return complex(); @@ -130,6 +134,8 @@ public SoundInstance preload(boolean b) { return complex(); } + public SoundInstance preload() { return preload(true); } + public SoundInstance asReferenceToEvent() { isEventReference = true; return complex(); diff --git a/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java b/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java deleted file mode 100644 index 21a4bdff3..000000000 --- a/common/src/main/java/dev/latvian/mods/kubejs/core/mixin/common/ParticleEngineMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.latvian.mods.kubejs.core.mixin.common; - -import dev.latvian.mods.kubejs.bindings.event.ClientEvents; -import dev.latvian.mods.kubejs.client.ParticleProviderRegistryEventJS; -import net.minecraft.client.particle.ParticleEngine; -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; - -@Mixin(ParticleEngine.class) -public abstract class ParticleEngineMixin { - - @Inject(method = "registerProviders", at = @At("RETURN")) - private void registerParticleProvidersKJS(CallbackInfo ci) { - ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryEventJS()); - } -} diff --git a/common/src/main/resources/kubejs-common.mixins.json b/common/src/main/resources/kubejs-common.mixins.json index ee64c5076..176a78b95 100644 --- a/common/src/main/resources/kubejs-common.mixins.json +++ b/common/src/main/resources/kubejs-common.mixins.json @@ -55,7 +55,6 @@ "LocalPlayerMixin", "MinecraftClientMixin", "OptionsMixin", - "ParticleEngineMixin", "ScreenMixin", "WindowMixin", "WorldOpenFlowsMixin", From aca8e0ada94d499614d4516aea752e2225212466 Mon Sep 17 00:00:00 2001 From: Notenoughmail <78008321+Notenoughmail@users.noreply.github.com> Date: Sat, 1 Jun 2024 21:46:30 -0700 Subject: [PATCH 5/5] Unsigned Alpha - Use sign-agnostic bitshift for particle color alphas - Include particle speed by default for simple providers --- .../latvian/mods/kubejs/client/KubeAnimatedParticle.java | 2 +- .../mods/kubejs/client/ParticleProviderRegistryEventJS.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java index 56abeb4cf..6e23e4918 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/KubeAnimatedParticle.java @@ -32,7 +32,7 @@ public void setFriction(float f) { public void setColor(Color color, boolean alpha) { setColor(color.getRgbJS()); if (alpha) { - setAlpha((color.getArgbJS() >> 24) / 255.0F); + setAlpha((color.getArgbJS() >>> 24) / 255.0F); } } diff --git a/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java index 7554507e0..3bd8999c3 100644 --- a/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java +++ b/common/src/main/java/dev/latvian/mods/kubejs/client/ParticleProviderRegistryEventJS.java @@ -18,7 +18,11 @@ public void register(ParticleType type, ParticleP } public void registerSimple(ParticleType type, Consumer particle) { - ParticleProviderRegistry.register(type, set -> (t, level, x, y, z, dx, dy, dz) -> Util.make(new KubeAnimatedParticle(level, set, x, y, z), particle)); + ParticleProviderRegistry.register(type, set -> (t, level, x, y, z, dx, dy, dz) -> Util.make(Util.make(() -> { + var kube = new KubeAnimatedParticle(level, set, x, y, z); + kube.setParticleSpeed(dx, dy, dz); + return kube; + }), particle)); } public void registerSimple(ParticleType type) {