166 lines
6.6 KiB
Java
166 lines
6.6 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.collect.Lists
|
|
* com.google.common.collect.Maps
|
|
* com.google.common.collect.Queues
|
|
* it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.client.particle;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Queues;
|
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.Queue;
|
|
import net.minecraft.client.Camera;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.particle.ElderGuardianParticleGroup;
|
|
import net.minecraft.client.particle.ItemPickupParticleGroup;
|
|
import net.minecraft.client.particle.NoRenderParticleGroup;
|
|
import net.minecraft.client.particle.Particle;
|
|
import net.minecraft.client.particle.ParticleGroup;
|
|
import net.minecraft.client.particle.ParticleProvider;
|
|
import net.minecraft.client.particle.ParticleRenderType;
|
|
import net.minecraft.client.particle.ParticleResources;
|
|
import net.minecraft.client.particle.QuadParticleGroup;
|
|
import net.minecraft.client.particle.TrackingEmitter;
|
|
import net.minecraft.client.renderer.culling.Frustum;
|
|
import net.minecraft.client.renderer.state.ParticlesRenderState;
|
|
import net.minecraft.core.particles.ParticleLimit;
|
|
import net.minecraft.core.particles.ParticleOptions;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.util.profiling.Profiler;
|
|
import net.minecraft.world.entity.Entity;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class ParticleEngine {
|
|
private static final List<ParticleRenderType> RENDER_ORDER = List.of(ParticleRenderType.SINGLE_QUADS, ParticleRenderType.ITEM_PICKUP, ParticleRenderType.ELDER_GUARDIANS);
|
|
protected ClientLevel level;
|
|
private final Map<ParticleRenderType, ParticleGroup<?>> particles = Maps.newIdentityHashMap();
|
|
private final Queue<TrackingEmitter> trackingEmitters = Queues.newArrayDeque();
|
|
private final Queue<Particle> particlesToAdd = Queues.newArrayDeque();
|
|
private final Object2IntOpenHashMap<ParticleLimit> trackedParticleCounts = new Object2IntOpenHashMap();
|
|
private final ParticleResources resourceManager;
|
|
private final RandomSource random = RandomSource.create();
|
|
|
|
public ParticleEngine(ClientLevel level, ParticleResources resourceManager) {
|
|
this.level = level;
|
|
this.resourceManager = resourceManager;
|
|
}
|
|
|
|
public void createTrackingEmitter(Entity entity, ParticleOptions particle) {
|
|
this.trackingEmitters.add(new TrackingEmitter(this.level, entity, particle));
|
|
}
|
|
|
|
public void createTrackingEmitter(Entity entity, ParticleOptions particle, int lifeTime) {
|
|
this.trackingEmitters.add(new TrackingEmitter(this.level, entity, particle, lifeTime));
|
|
}
|
|
|
|
public @Nullable Particle createParticle(ParticleOptions options, double x, double y, double z, double xa, double ya, double za) {
|
|
Particle particle = this.makeParticle(options, x, y, z, xa, ya, za);
|
|
if (particle != null) {
|
|
this.add(particle);
|
|
return particle;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private <T extends ParticleOptions> @Nullable Particle makeParticle(T options, double x, double y, double z, double xa, double ya, double za) {
|
|
ParticleProvider provider = (ParticleProvider)this.resourceManager.getProviders().get(BuiltInRegistries.PARTICLE_TYPE.getId(options.getType()));
|
|
if (provider == null) {
|
|
return null;
|
|
}
|
|
return provider.createParticle(options, this.level, x, y, z, xa, ya, za, this.random);
|
|
}
|
|
|
|
public void add(Particle p) {
|
|
Optional<ParticleLimit> limit = p.getParticleLimit();
|
|
if (limit.isPresent()) {
|
|
if (this.hasSpaceInParticleLimit(limit.get())) {
|
|
this.particlesToAdd.add(p);
|
|
this.updateCount(limit.get(), 1);
|
|
}
|
|
} else {
|
|
this.particlesToAdd.add(p);
|
|
}
|
|
}
|
|
|
|
public void tick() {
|
|
this.particles.forEach((type, group) -> {
|
|
Profiler.get().push(type.name());
|
|
group.tickParticles();
|
|
Profiler.get().pop();
|
|
});
|
|
if (!this.trackingEmitters.isEmpty()) {
|
|
ArrayList removed = Lists.newArrayList();
|
|
for (TrackingEmitter emitter : this.trackingEmitters) {
|
|
emitter.tick();
|
|
if (emitter.isAlive()) continue;
|
|
removed.add(emitter);
|
|
}
|
|
this.trackingEmitters.removeAll(removed);
|
|
}
|
|
if (!this.particlesToAdd.isEmpty()) {
|
|
Particle particle;
|
|
while ((particle = this.particlesToAdd.poll()) != null) {
|
|
this.particles.computeIfAbsent(particle.getGroup(), this::createParticleGroup).add(particle);
|
|
}
|
|
}
|
|
}
|
|
|
|
private ParticleGroup<?> createParticleGroup(ParticleRenderType type) {
|
|
if (type == ParticleRenderType.ITEM_PICKUP) {
|
|
return new ItemPickupParticleGroup(this);
|
|
}
|
|
if (type == ParticleRenderType.ELDER_GUARDIANS) {
|
|
return new ElderGuardianParticleGroup(this);
|
|
}
|
|
if (type == ParticleRenderType.NO_RENDER) {
|
|
return new NoRenderParticleGroup(this);
|
|
}
|
|
return new QuadParticleGroup(this, type);
|
|
}
|
|
|
|
protected void updateCount(ParticleLimit limit, int change) {
|
|
this.trackedParticleCounts.addTo((Object)limit, change);
|
|
}
|
|
|
|
public void extract(ParticlesRenderState particlesRenderState, Frustum frustum, Camera camera, float partialTickTime) {
|
|
for (ParticleRenderType particleType : RENDER_ORDER) {
|
|
ParticleGroup<?> particles = this.particles.get(particleType);
|
|
if (particles == null || particles.isEmpty()) continue;
|
|
particlesRenderState.add(particles.extractRenderState(frustum, camera, partialTickTime));
|
|
}
|
|
}
|
|
|
|
public void setLevel(@Nullable ClientLevel level) {
|
|
this.level = level;
|
|
this.clearParticles();
|
|
this.trackingEmitters.clear();
|
|
}
|
|
|
|
public String countParticles() {
|
|
return String.valueOf(this.particles.values().stream().mapToInt(ParticleGroup::size).sum());
|
|
}
|
|
|
|
private boolean hasSpaceInParticleLimit(ParticleLimit limit) {
|
|
return this.trackedParticleCounts.getInt((Object)limit) < limit.limit();
|
|
}
|
|
|
|
public void clearParticles() {
|
|
this.particles.clear();
|
|
this.particlesToAdd.clear();
|
|
this.trackingEmitters.clear();
|
|
this.trackedParticleCounts.clear();
|
|
}
|
|
}
|
|
|