Skip to content

Commit

Permalink
Merge pull request #877 from Notenoughmail/1.21-sounds-and-particles
Browse files Browse the repository at this point in the history
[1.21] SoundEvent and ParticleType Utilities
  • Loading branch information
LatvianModder authored Aug 15, 2024
2 parents 4c0bda3 + 97e545a commit e1b0b2d
Show file tree
Hide file tree
Showing 12 changed files with 438 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import dev.latvian.mods.kubejs.client.EntityRendererRegistryKubeEvent;
import dev.latvian.mods.kubejs.client.LangKubeEvent;
import dev.latvian.mods.kubejs.client.MenuScreenRegistryKubeEvent;
import dev.latvian.mods.kubejs.client.ParticleProviderRegistryKubeEvent;
import dev.latvian.mods.kubejs.event.EventGroup;
import dev.latvian.mods.kubejs.event.EventHandler;
import dev.latvian.mods.kubejs.event.EventTargetType;
Expand All @@ -29,4 +30,5 @@ public interface ClientEvents {
EventHandler DEBUG_RIGHT = GROUP.client("rightDebugInfo", () -> DebugInfoKubeEvent.class);
TargetedEventHandler<ResourceLocation> ATLAS_SPRITE_REGISTRY = GROUP.client("atlasSpriteRegistry", () -> AtlasSpriteRegistryKubeEvent.class).requiredTarget(EventTargetType.ID);
TargetedEventHandler<String> LANG = GROUP.client("lang", () -> LangKubeEvent.class).requiredTarget(EventTargetType.STRING);
EventHandler PARTICLE_PROVIDER_REGISTRY = GROUP.client("particleProviderRegistry", () -> ParticleProviderRegistryKubeEvent.class);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public List<PackResources> inject(List<PackResources> original) {

KubeJSPlugins.forEachPlugin(internalAssetPack, KubeJSPlugin::generateAssets);

internalAssetPack.buildSounds();

var langMap = new HashMap<LangKubeEvent.Key, String>();
var langEvents = new HashMap<String, LangKubeEvent>();
var enUsLangEvent = langEvents.computeIfAbsent("en_us", s -> new LangKubeEvent(s, langMap));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package dev.latvian.mods.kubejs.client;

import dev.latvian.mods.kubejs.color.Color;
import dev.latvian.mods.kubejs.typings.Info;
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.util.RandomSource;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;

import java.util.function.Consumer;

public class KubeAnimatedParticle extends SimpleAnimatedParticle {

private Float2IntFunction lightColorFunction;
@Nullable
private Consumer<KubeAnimatedParticle> onTick;

public KubeAnimatedParticle(ClientLevel level, double x, double y, double z, SpriteSet sprites) {
super(level, x, y, z, sprites, 0.0125F);
setLifetime(20);
setSpriteFromAge(sprites);
lightColorFunction = super::getLightColor;
}

public void setGravity(float g) {
gravity = g;
}

@Info(value = "Sets teh friction of the particle, the particle's motion is multiplied by this value every tick")
public void setFriction(float f) {
friction = f;
}

public void setColor(Color color, boolean alpha) {
setColor(color.getRgbJS());
if (alpha) {
setAlpha((color.getArgbJS() >>> 24) / 255F);
}
}

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;
}

public void onTick(@Nullable Consumer<KubeAnimatedParticle> tick) {
onTick = tick;
}

public void setSpeed(Vec3 speed) {
setParticleSpeed(speed.x(), speed.y(), speed.z());
}

// 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 RandomSource getRandom() { return random; }

@Override
public int getLightColor(float partialTick) {
return lightColorFunction.get(partialTick);
}

@Override
public void tick() {
super.tick();
if (onTick != null) {
onTick.accept(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent;
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
import net.neoforged.neoforge.client.event.RegisterShadersEvent;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent;
Expand Down Expand Up @@ -170,4 +171,11 @@ public ResourceLocation getRenderOverlayTexture(Minecraft mc) {
}
}
}

@SubscribeEvent
public static void registerParticleProviders(RegisterParticleProvidersEvent event) {
if (ClientEvents.PARTICLE_PROVIDER_REGISTRY.hasListeners()) {
ClientEvents.PARTICLE_PROVIDER_REGISTRY.post(new ParticleProviderRegistryKubeEvent(event));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.latvian.mods.kubejs.client;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import java.util.ArrayList;
import java.util.List;

public class ParticleGenerator {

public transient List<String> textures = new ArrayList<>();

public ParticleGenerator texture(String texture) {
textures.add(texture);
return this;
}

public ParticleGenerator textures(List<String> textures) {
this.textures = textures;
return this;
}

public JsonObject toJson() {
var array = new JsonArray(textures.size());
textures.forEach(array::add);
var json = new JsonObject();
json.add("textures", array);
return json;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dev.latvian.mods.kubejs.client;

import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleEngine;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;

import java.util.function.Consumer;

public class ParticleProviderRegistryKubeEvent implements ClientKubeEvent {

private final RegisterParticleProvidersEvent parent;

public ParticleProviderRegistryKubeEvent(RegisterParticleProvidersEvent event) {
parent = event;
}

public <T extends ParticleOptions> void register(ParticleType<T> type, SpriteSetParticleProvider<T> spriteProvider) {
parent.registerSpriteSet(type, spriteProvider);
}

public <T extends ParticleOptions> void register(ParticleType<T> type, Consumer<KubeAnimatedParticle> particle) {
parent.registerSpriteSet(type, set -> (type1, level, x, y, z, xSpeed, ySpeed, zSpeed) -> {
var kube = new KubeAnimatedParticle(level, x, y, z, set);
kube.setParticleSpeed(xSpeed, ySpeed, zSpeed);
particle.accept(kube);
return kube;
});
}

public <T extends ParticleOptions> void register(ParticleType<T> type) {
register(type, p -> {});
}

public <T extends ParticleOptions> void registerSpecial(ParticleType<T> type, ParticleProvider<T> provider) {
parent.registerSpecial(type, provider);
}

@FunctionalInterface
public interface SpriteSetParticleProvider<T extends ParticleOptions> extends ParticleEngine.SpriteParticleRegistration<T> {
Particle create(T type, ClientLevel clientLevel, double x, double y, double z, SpriteSet sprites, double xSpeed, double ySpeed, double zSpeed);

default ParticleProvider<T> create(SpriteSet sprites) {
return (type, level, x, y, z, xSpeed, ySpeed, zSpeed) -> create(type, level, x, y, z, sprites, xSpeed, ySpeed, zSpeed);
}
}
}
171 changes: 171 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/client/SoundsGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
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.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 SoundsGenerator {

private final Map<String, SoundGen> sounds = new HashMap<>();

public void addSound(String path, Consumer<SoundGen> consumer, boolean overlayExisting) {
if (overlayExisting && sounds.containsKey(path)) {
consumer.accept(sounds.get(path));
} else {
sounds.put(path, Util.make(new SoundGen(), consumer));
}
}

public void addSound(String path, Consumer<SoundGen> consumer) {
addSound(path, consumer, false);
}

public JsonObject toJson() {
var json = new JsonObject();
sounds.forEach((path, gen) -> json.add(path, gen.toJson()));
return json;
}

public static class SoundGen {

private boolean replace = false;
@Nullable
private String subtitle;
private final List<SoundInstance> instances = new ArrayList<>();

public SoundGen replace(boolean b) {
replace = b;
return this;
}

public SoundGen replace() { return replace(true); }

public SoundGen subtitle(@Nullable String subtitle) {
this.subtitle = subtitle;
return this;
}

public SoundGen sound(String file) {
instances.add(new SoundInstance(file));
return this;
}

public SoundGen sounds(String... sounds) {
instances.addAll(Stream.of(sounds).map(SoundInstance::new).toList());
return this;
}

public SoundGen sound(String file, Consumer<SoundInstance> consumer) {
instances.add(Util.make(new SoundInstance(file), consumer));
return this;
}

public JsonObject toJson() {
var json = new JsonObject();
if (replace) {
json.addProperty("replace", true);
}
if (subtitle != null) {
json.addProperty("subtitle", subtitle);
}
if (!instances.isEmpty()) {
var array = new JsonArray(instances.size());
instances.forEach(inst -> array.add(inst.toJson()));
json.add("sounds", array);
}
return json;
}

}

public static class SoundInstance {

private final String 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(String 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 stream() { return stream(true); }

public SoundInstance attenuationDistance(int i) {
attenuationDistance = i;
return complex();
}

public SoundInstance preload(boolean b) {
preload = b;
return complex();
}

public SoundInstance preload() { return preload(true); }

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;
}
}
}
Loading

0 comments on commit e1b0b2d

Please sign in to comment.